Blame view

src/routine_manager/RequestSerializer.py 9.4 KB
3c179769   Jeremy   userSimulator / a...
1
from django.conf import settings
ddf59dd4   haribo   Remaniement :
2
from common.models import *
eea995c9   haribo   Date: 16/06/2016
3
4
5
import xml.etree.ElementTree as ET
import sys
from xml.dom import minidom
3dbda6a0   haribo   Date: 17/06/2016
6
7
8
from .validators import check_plan_validity
import re
from decimal import Decimal
3c179769   Jeremy   userSimulator / a...
9
10
11
from jdcal import gcal2jd, jd2gcal
import time
import datetime
bca9a283   Jeremy   Reworked the sche...
12
import utils.Logger as L
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
13
14
import scheduler.tasks as task
#import scheduler.tasks
65149de7   Jeremy   Update
15
log = L.setupLogger("RequestSerializerLogger", "RequestSerializer")
eea995c9   haribo   Date: 16/06/2016
16
17
18

def prettify(elem):
    """
3c179769   Jeremy   userSimulator / a...
19
        :returns : A pretty-printed XML string for the Element elem
eea995c9   haribo   Date: 16/06/2016
20
21
22
23
24
25
    """
    rough_string = ET.tostring(elem, 'utf-8')
    reparsed = minidom.parseString(rough_string)
    return reparsed.toprettyxml(indent="    ")

class RequestSerializer():
3c179769   Jeremy   userSimulator / a...
26
27
    submit = False
    relative = False
eea995c9   haribo   Date: 16/06/2016
28
29
30
31
    """
        Serializes and unserializes a request, with all children (sequences, albums and plans)
        Format : XML
        Only serializes the wanted fields
3c179769   Jeremy   userSimulator / a...
32

eea995c9   haribo   Date: 16/06/2016
33
34
35
36
37
38
39
40
41
42
43
44
        Entry point(s) :
            - serialize
    """

    def serialize(self, req, file_name):
        """
            Serializes the request into the given file
        """
        request = ET.Element("request", name=req.name, scientific_program=req.scientific_program.name,
                             target_type=req.target_type)
        for seq in req.sequences.all():
            sequence = ET.SubElement(request, "sequence", name=seq.name, target_coords=seq.target_coords,
e5189e4f   haribo   Date: 20/06/2016
45
46
                                     jd1=str(seq.jd1), jd2=str(seq.jd2))
            sequence.set("duration", str(seq.duration * 86400))
eea995c9   haribo   Date: 16/06/2016
47
            for alb in seq.albums.all():
abfb02e2   Jeremy   Device Model is n...
48
                album = ET.SubElement(sequence, "album", name=alb.name, detector=alb.detector.name)
eea995c9   haribo   Date: 16/06/2016
49
                for plan in alb.plans.all():
abfb02e2   Jeremy   Device Model is n...
50
                    pl = ET.SubElement(album, "plan", name=plan.name, filter=plan.filter.name, nb_images=str(plan.nb_images))
e5189e4f   haribo   Date: 20/06/2016
51
                    pl.set("duration", str(plan.duration * 86400))
eea995c9   haribo   Date: 16/06/2016
52
53
54
55

        with open(file_name, "w") as file:
            file.write(prettify(request))

3dbda6a0   haribo   Date: 17/06/2016
56
    def unserialize(self, xml_data, pyros_user):
3c179769   Jeremy   userSimulator / a...
57
        TIMESTAMP_JD = 2440587.500000
eea995c9   haribo   Date: 16/06/2016
58
59
60
        """
            Unserializes the request read into file_name
            Throws exceptions in case of invalid file or values
3c179769   Jeremy   userSimulator / a...
61

eea995c9   haribo   Date: 16/06/2016
62
63
            Directly saves the objects in DB
            The request still need to be submitted afterward !
3c179769   Jeremy   userSimulator / a...
64

3dbda6a0   haribo   Date: 17/06/2016
65
            :returns : "" (empty string) in case of success, error message (string) instead
eea995c9   haribo   Date: 16/06/2016
66
        """
3dbda6a0   haribo   Date: 17/06/2016
67
68
69
70
71
72
73

        try:
            root = ET.fromstring(xml_data)
        except ET.ParseError as E:
            return "Invalid file : " + str(E)

        self.pyros_user = pyros_user
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
74
        print("RS: pyros user is ", pyros_user)
3dbda6a0   haribo   Date: 17/06/2016
75
76
77
78
79
80
81
82
        self.request = None

        """ self.sequences will be a [(seq, album_list), ...], and same thing for album """
        self.sequences = []
        ret = self.unserialize_request(root)
        if ret != "":
            return ret

3c179769   Jeremy   userSimulator / a...
83
        if (settings.DEBUG):
f7dd3df1   Jeremy   Update simulators...
84
            log.info("Request submit " + str(self.submit))
3c179769   Jeremy   userSimulator / a...
85
86
        if self.submit:
            self.request.submitted = 1
3dbda6a0   haribo   Date: 17/06/2016
87
88
        self.request.save()
        for sequence, albums in self.sequences:
3c179769   Jeremy   userSimulator / a...
89
            if self.relative:
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
90
                # 86400 = nb seconds in 24 h
e27f5476   Etienne Pallier   Settings TIME_ZON...
91
92
                # time.localtime(time.time()) donne l'heure française
                # time.gmttime(time.time()) donne l'heure gmt
3c179769   Jeremy   userSimulator / a...
93
94
                sequence.jd1 = (time.time() + float(sequence.jd1)) / 86400 + TIMESTAMP_JD
                sequence.jd2 = (time.time() + float(sequence.jd2)) / 86400 + TIMESTAMP_JD
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
95
96
97
98
99
100
                #print("********* jd1,jd2 ", sequence.jd1, sequence.jd2)

                # EP avirer
                #sequence.jd1 += float( (1/24)*2 )
                #sequence.jd2 += float( (1/24)*2 )

3dbda6a0   haribo   Date: 17/06/2016
101
            sequence.request = self.request
3dbda6a0   haribo   Date: 17/06/2016
102
103
104
105
106
107
108
109
            sequence.save()
            for album, plans in albums:
                album.sequence = sequence
                album.save()
                for plan in plans:
                    plan.album = album
                    plan.save()
                    check_plan_validity(plan)
3c179769   Jeremy   userSimulator / a...
110
        if (self.request.submitted):
cd0149f5   Etienne Pallier   progress made for...
111
112
113
            #ret = task.scheduling.delay(first_schedule=False, alert=False)
            if settings.USE_CELERY:
                print("RS: schedule WITH CELERY")
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
114
115
                #ret = scheduler.tasks.scheduling.delay(first_schedule=False, alert=False)
                ret = task.scheduling.delay(first_schedule=False, alert=False)
cd0149f5   Etienne Pallier   progress made for...
116
117
            else:
                print("RS: schedule WITHOUT CELERY")
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
118
119
                #ret = scheduler.tasks.scheduling().run(first_schedule=False, alert=False)
                ret = task.scheduling().run(first_schedule=False, alert=False)
cd0149f5   Etienne Pallier   progress made for...
120

3dbda6a0   haribo   Date: 17/06/2016
121
122
123
        return ""

    def unserialize_request(self, request):
9b5bad52   haribo   Commented all the...
124
        '''
3c179769   Jeremy   userSimulator / a...
125
            Receives an xml.etree request and unserialize it
9b5bad52   haribo   Commented all the...
126
127
        '''

3dbda6a0   haribo   Date: 17/06/2016
128
129
        if request.tag != "request":
            return "Main object should be a request (found %s instead)" % (request.tag,)
3c179769   Jeremy   userSimulator / a...
130
        possible_attribs = ["name", "scientific_program", "target_type", "submitted", "relative"]
3dbda6a0   haribo   Date: 17/06/2016
131
132
133
134
135
136
137
138
139
140
141
142
143

        self.request = Request(pyros_user=self.pyros_user, is_alert=False, complete=False, submitted=False)

        for name, value in request.attrib.items():
            if name not in possible_attribs:
                return "Unknown attribute %s in request" % (name,)
            if name == "scientific_program":
                try:
                    sp = ScientificProgram.objects.get(name=value)
                    self.request.scientific_program = sp
                except Exception as E:
                    print(str(E))
                    return "Invalid scientific program %s" % (value,)
3c179769   Jeremy   userSimulator / a...
144
145
146
147
148
149
150
151
152
153
154
155
            elif name == "submitted":
                try:
                    self.submit = bool(int(value))
                except Exception as E:
                    print(str(E))
                    return ("Invalid value for submitted")
            elif name == "relative":
                try:
                    self.relative = bool(int(value))
                except Exception as E:
                    print(str(E))
                    return ("Invalid value for submitted")
3dbda6a0   haribo   Date: 17/06/2016
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
            else:
                self.request.__dict__[name] = value

        for sequence in request:
            ret = self.unserialize_sequence(sequence)
            if ret != "":
                return ret
        return ""

    def unserialize_sequence(self, sequence):
        if sequence.tag != "sequence":
            return "A request can only have 'sequence' children (found %s instead)" % (sequence.tag,)
        possible_attribs = ["name", "target_coords", "jd1", "jd2", "duration"]

        seq = Sequence(request=self.request, status=Sequence.INCOMPLETE)

        for name, value in sequence.attrib.items():
            if name not in possible_attribs:
                return "Unknown attribute %s in sequence" % (name,)
            if name == "name":
                seq.name = value
            elif name == "target_coords":
                seq.target_coords = value
            elif name == "jd1":
                seq.jd1 = Decimal(value)
            elif name == "jd2":
                seq.jd2 = Decimal(value)
            elif name == "duration":
e5189e4f   haribo   Date: 20/06/2016
184
                seq.duration = Decimal(value) / 86400
3dbda6a0   haribo   Date: 17/06/2016
185

1a317dbd   haribo   TODOs et modifs m...
186
        # TODO: faire des checks ?? j'imagine, par exemple pour la cohérence des valeurs
3dbda6a0   haribo   Date: 17/06/2016
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
        album_list = []
        self.sequences.append((seq, album_list))

        for album in sequence:
            ret = self.unserialize_album(album, seq, album_list)
            if ret != "":
                return ret
        return ""

    def unserialize_album(self, album, sequence, album_list):
        if album.tag != "album":
            return "A sequence can only have 'album' children (found %s instead)" % (album.tag,)
        possible_attribs = ["name", "detector"]

        alb = Album(sequence=sequence)

        for name, value in album.attrib.items():
            if name not in possible_attribs:
                return "Unknown attribute %s in album" % (name,)
            if name == "detector":
                try:
abfb02e2   Jeremy   Device Model is n...
208
                    detector = Detector.objects.get(name=value)
3dbda6a0   haribo   Date: 17/06/2016
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
                    alb.detector = detector
                except Exception as E:
                    print(str(E))
                    return "Invalid detector %s" % (value,)
            elif name == "name":
                alb.name = value
        plan_list = []
        album_list.append((alb, plan_list))

        for plan in album:
            ret = self.unserialize_plan(plan, alb, plan_list)
            if ret != "":
                return ret
        return ""


    def unserialize_plan(self, plan, album, plan_list):
        if plan.tag != "plan":
            return "An album can only have 'plan' children (found %s instead)" % (plan.tag,)
        possible_attribs = ["name", "filter", "duration", "nb_images"]

        pl = Plan(album=album)

        for name, value in plan.attrib.items():
            if name not in possible_attribs:
                return "Unknown attribute %s in plan" % (name,)
            if name == "filter":
                try:
abfb02e2   Jeremy   Device Model is n...
237
                    filter = Filter.objects.get(name=value)
3dbda6a0   haribo   Date: 17/06/2016
238
239
240
241
242
243
                    pl.filter = filter
                except Exception as E:
                    return "Invalid filter %s" % (value,)
            elif name == "name":
                pl.name = value
            elif name == "duration":
e5189e4f   haribo   Date: 20/06/2016
244
                pl.duration = Decimal(value) / 86400
3dbda6a0   haribo   Date: 17/06/2016
245
246
247
            elif name == "nb_images":
                pl.nb_images = int(value)

5d61cbfe   haribo   Just adding / rem...
248
        # TODO: quelques checks ...
3dbda6a0   haribo   Date: 17/06/2016
249
250
251

        plan_list.append(pl)
        return ""