messages.py 76.4 KB
Newer Older
1
2
3
# -*- coding: utf-8 -*-

"""
4
5
6
7

About the library:
-----------------

8
9
10
11
12
13
14
15
16
This module provides the API message formats used in F-Interop.

The idea is to be able to have an
- organized and centralized way of dealing with the big amount of messages formats used in the platform;
- to be able to import (or just copy/paste) these messages formats from any component in the F-Interop platform,
- re-use this also for the integration testing;
- to have version control the messages e.g. messages_testcase_start API v1 and API v2;
- to have a direct way of exporting this as doc.

17
18
19
20
21
22
23
24

F-Interop conventions:
---------------------
- if event is a service request then the routing key (r_key) is control.someFunctionality.service
- a reply to a service will be on topic/r_key : control.someFunctionality.service.reply
- reply.correlation_id = request.correlation_id


25
26
Usage:
------
27
>>> from messages import * # doctest: +SKIP
Federico Sismondi's avatar
Federico Sismondi committed
28
>>> m = MsgTestCaseSkip(testcase_id = 'some_testcase_id')
29
>>> m
30
MsgTestCaseSkip(_api_version = 1.0.1, _type = testcoordination.testcase.skip, description = Skip testcase, node = someNode, testcase_id = some_testcase_id, )
31
32
>>> m.routing_key
'control.testcoordination'
33
34
>>> m.message_id # doctest: +SKIP
'802012eb-24e3-45c4-9dcc-dc293c584f63'
35
>>> m.testcase_id
Federico Sismondi's avatar
Federico Sismondi committed
36
'some_testcase_id'
37

38
# also we can modify some of the fields (rewrite the default ones)
Federico Sismondi's avatar
Federico Sismondi committed
39
>>> m = MsgTestCaseSkip(testcase_id = 'TD_COAP_CORE_03')
40
>>> m
41
MsgTestCaseSkip(_api_version = 1.0.1, _type = testcoordination.testcase.skip, description = Skip testcase, node = someNode, testcase_id = TD_COAP_CORE_03, )
42
>>> m.testcase_id
Federico Sismondi's avatar
Federico Sismondi committed
43
'TD_COAP_CORE_03'
44

45
46
# and even export the message in json format (for example for sending the message though the amqp event bus)
>>> m.to_json()
47
'{"_api_version": "1.0.1", "_type": "testcoordination.testcase.skip", "description": "Skip testcase", "node": "someNode", "testcase_id": "TD_COAP_CORE_03"}'
Federico Sismondi's avatar
add doc    
Federico Sismondi committed
48

49
# We can use the Message class to import json into Message objects:
Federico Sismondi's avatar
add doc    
Federico Sismondi committed
50
51
>>> m=MsgTestSuiteStart()
>>> m.to_json()
52
'{"_api_version": "1.0.1", "_type": "testcoordination.testsuite.start", "description": "Event test suite START"}'
Federico Sismondi's avatar
add doc    
Federico Sismondi committed
53
54
55
>>> json_message = m.to_json()
>>> obj=Message.from_json(json_message)
>>> type(obj)
56
<class 'messages.MsgTestSuiteStart'>
57

58
# We can use the library for generating error responses:
59
60
61
62
63
64
# the request:
>>> m = MsgSniffingStart()
>>>
# the error reply (note that we pass the message of the request to build the reply):
>>> err = MsgErrorReply(m)
>>> err
65
MsgErrorReply(_api_version = 1.0.1, _type = sniffing.start, error_code = Some error code TBD, error_message = Some error message TBD, ok = False, )
66
67
68
69
70
71
72
73
74
>>> m.reply_to
'control.sniffing.service.reply'
>>> err.routing_key
'control.sniffing.service.reply'

>>> m.correlation_id # doctest: +SKIP
'360b0f67-4455-43e3-a00f-eca91f2e84da'
>>> err.correlation_id # doctest: +SKIP
'360b0f67-4455-43e3-a00f-eca91f2e84da'
Federico Sismondi's avatar
add doc    
Federico Sismondi committed
75

76
77
78
"""

from collections import OrderedDict
79
import time
80
81
82
import json
import uuid

83
API_VERSION = '0.1.72'
84

85
86
87
88
89
90
91
92
93
94

# TODO use metaclasses instead?
class NonCompliantMessageFormatError(Exception):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return repr(self.value)


Federico Sismondi's avatar
Federico Sismondi committed
95
class Message(object):
96
    def __init__(self, **kwargs):
97
98
        global API_VERSION

99
100
101
102
103
104
105
        try:
            # hard copy the message template
            self._msg_data = {k: v for k, v in self._msg_data_template.items()}
        except AttributeError: # if message is built directly using Message class then there's no data template
            self._msg_data={}
            self._msg_data_template={}

106

107
108
        # init properties
        self._properties = dict(
109
110
111
            content_type="application/json",
            message_id=str(uuid.uuid4()),
            timestamp=int(time.time())
112
113
        )

114
        try:
115
            # TODO deprecate .service in favour of .request
116
            if self.routing_key.endswith(".service"):
117
118
                import logging
                logging.warning('(!) deprecate .service in favour of .request')
119
120
                self._properties["reply_to"] = "%s.%s" % (self.routing_key, "reply")
                self._properties["correlation_id"] = self._properties["message_id"]
121
122
123
124
125

            elif self.routing_key.endswith(".request"):
                self._properties["reply_to"] = self.routing_key.replace(".request", ".reply")
                self._properties["correlation_id"] = self._properties["message_id"]

126
        except AttributeError:
127
            pass
128

129
        # rewrite default data fields with the passed args
130
131
132
        self._msg_data.update(kwargs)

        # add API's version
133
        if "_api_version" not in self._msg_data:
134
            self._msg_data["_api_version"] = API_VERSION
135

Federico Sismondi's avatar
Federico Sismondi committed
136
        # add values as object's attributes
137
138
139
        for key in self._msg_data:
            setattr(self, key, self._msg_data[key])

140
141
142
143
        # add props as objects attributes
        for key in self._properties:
            setattr(self, key, self._properties[key])

144
145
    def to_dict(self):
        resp = {}
146
147
        # let's use sorted so API returns items inside always in the same order
        for field in sorted(self._msg_data.keys()):
148
            resp[field] = getattr(self, field)
149

150
151
152
153
154
155
156
157
        return resp

    def to_odict(self):
        resp = {}
        # let's use sorted so API returns items inside always in the same order
        for field in sorted(self._msg_data.keys()):
            resp[field] = getattr(self, field)

158
        return OrderedDict(sorted(resp.items(), key=lambda t: t[0]))  # sorted by key
159
160
161
162

    def to_json(self):
        return json.dumps(self.to_dict())

163
    def get_properties(self):
164
165
166
167
        resp = OrderedDict()
        for field in self._properties:
            resp[field] = getattr(self, field)
        return resp
168

169
    def __str__(self):
170
171
172
173
174
175
176
        s = " - " * 20 + "\n"
        s += "Message routing key: %s" % self.routing_key
        s += "\n -  -  - \n"
        s += "Message properties: %s" % json.dumps(self.get_properties(), indent=4, )
        s += "\n -  -  - \n"
        s += "Message body: %s" % json.dumps(self.to_dict(), indent=4, )
        s += "\n" + " - " * 20
177
        return s
178

179
180
    def update_properties(self, **kwargs):
        for key, value in kwargs.items():
181
182
183
            # if key in self._properties:
            #     setattr(self, key, value)
            setattr(self, key, value)
184

185
186
    @classmethod
    def from_json(cls, body):
187
188
189
190
191
192
193
194
195
196
        """
        :param body: json string or string encoded as utf-8
        :return:  Message object generated from the body
        :raises NonCompliantMessageFormatError: If the message cannot be build from the provided json
        """

        if type(body) is str:
            message_dict = json.loads(body)
        # Note: pika re-encodes json.dumps strings as utf-8 for some reason, the following line undoes this
        elif type(body) is bytes:
197
            message_dict = json.loads(body.decode("utf-8"))
198
        else:
199
            raise NonCompliantMessageFormatError("Not a Json")
200

201
202
203
204
205
206
207
208
209
210
211
        return cls.from_dict(message_dict)

    @classmethod
    def from_dict(cls, message_dict):
        """
        :param body: dict
        :return:  Message object generated from the body
        :raises NonCompliantMessageFormatError: If the message cannot be build from the provided json
        """
        assert type(message_dict) is dict

212
        message_type = message_dict["_type"]
213

214
215
216
        if message_type in message_types_dict:
            return message_types_dict[message_type](**message_dict)
        else:
217
218
            raise NonCompliantMessageFormatError("Cannot load json message: %s" % str(message_dict))

219
    def __repr__(self):
220
        ret = "%s(" % self.__class__.__name__
221
        for key, value in self.to_dict().items():
222
223
            ret += "%s = %s, " % (key, value)
        ret += ")"
224
225
        return ret

226

227
228
229
230
231
class MsgReply(Message):
    """
    Auxiliary class which creates replies messages with fields based on the request.
    Routing key, corr_id and _type are generated based on the request message
    """
232

233
    def __init__(self, request_message=None, **kwargs):
234

235
236
237
238
239
240
        if request_message and hasattr(request_message, "routing_key"):
            # TODO (!) deprecate .service in favour of .request
            if request_message.routing_key.endswith(".service"):
                import logging
                logging.warning('(!) messages library | deprecate .service in favour of .request')
                self.routing_key = request_message.routing_key + ".reply"
241

242
243
244
245
246
247
248
249
250
251
            elif self.routing_key.endswith(".request"):
                self.routing_key = self.routing_key.replace(".request", ".reply")

            # if not data template, then let's build one for a reply
            # (possible when creating a MsgReply directly and not by using subclass)
            if not hasattr(self, "_msg_data_template"):
                self._msg_data_template = {
                    "_type": request_message._type,
                    "ok": True,
                }
252

253
            super(MsgReply, self).__init__(**kwargs)
254

255
256
257
            # overwrite correlation id template and attribute
            self._properties["correlation_id"] = request_message.correlation_id
            self.correlation_id = request_message.correlation_id
258

259
        else:  # note this doesnt generate amqp properties
260
            import logging
261
            logging.warning('(!) messages library | lazy response built, generating reply message without corr_id')
262
            super(MsgReply, self).__init__(**kwargs)
263

264
265
266
267
268
269
270
271
    def correlate_to(self, request_message):
        """
        add to reply message the right correlation information to request
        """
        # overwrite correlation id template and attribute
        self._properties["correlation_id"] = request_message.correlation_id
        self.correlation_id = request_message.correlation_id

272
273
274

class MsgErrorReply(MsgReply):
    """
275
    see section "F-Interop conventions" on top
276
    """
277

Federico Sismondi's avatar
Federico Sismondi committed
278
279
    def __init__(self, request_message, **kwargs):
        assert request_message
280
        # msg_data_template doesnt include _type cause this class is generic, we can only get this at init from request
Federico Sismondi's avatar
Federico Sismondi committed
281
        # so, let's copy the _type from request and let the MsgReply handle the rest of the fields
282
        self._msg_data_template["_type"] = request_message._type
283
        super(MsgErrorReply, self).__init__(request_message, **kwargs)
284
285

    _msg_data_template = {
286
        "ok": False,
287
        "error_message": "Some error message TBD",
288
        "error_code": "Some error code TBD"
289
290
    }

Federico Sismondi's avatar
Federico Sismondi committed
291

292
# # # # # # CORE API messages # # # # #
293
294

class MsgOrchestratorVersionReq(Message):
295
296
297
298
299
300
301
302
303
    """
    Requirements: ...

    Type: Event

    Pub/Sub: UI -> SO

    Description: Message for returning current version of SO
    """
304
    routing_key = "control.orchestrator.version.request"
305
306

    _msg_data_template = {
Federico Sismondi's avatar
Federico Sismondi committed
307
        "_type": "orchestrator.version.request"
308
    }
309

Federico Sismondi's avatar
Federico Sismondi committed
310

311
312
313
314
315
316
317
318
319
320
class MsgOrchestratorUsersList(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: UI -> SO

    Description: Message for returning user list of SO
    """
321
    routing_key = "control.orchestrator.users.list.request"
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337

    _msg_data_template = {
        "_type": "orchestrator.users.list.request"
    }


class MsgOrchestratorUserAdd(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: UI -> SO

    Description: Message for adding a user to SO
    """
338

339
    routing_key = "control.orchestrator.users.add.request"
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355

    _msg_data_template = {
        "_type": "orchestrator.users.add.request"
    }


class MsgOrchestratorUserDelete(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: UI -> SO

    Description: Message for deleting a user from SO
    """
356

357
    routing_key = "control.orchestrator.users.delete.request"
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373

    _msg_data_template = {
        "_type": "orchestrator.users.delete.request"
    }


class MsgOrchestratorUserGet(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: UI -> SO

    Description: Message for getting a user from SO
    """
374

375
    routing_key = "control.orchestrator.users.get.request"
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391

    _msg_data_template = {
        "_type": "orchestrator.users.get.request"
    }


class MsgOrchestratorSessionsList(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: UI -> SO

    Description: Message for listing sessions from SO
    """
392
    routing_key = "control.orchestrator.sessions.list.request"
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408

    _msg_data_template = {
        "_type": "orchestrator.sessions.list.request"
    }


class MsgOrchestratorSessionsGet(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: UI -> SO

    Description: Message for getting a session from SO
    """
409
    routing_key = "control.orchestrator.sessions.get.request"
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425

    _msg_data_template = {
        "_type": "orchestrator.sessions.get.request"
    }


class MsgOrchestratorSessionsAdd(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: UI -> SO

    Description: Message for adding a session to SO
    """
426
    routing_key = "control.orchestrator.sessions.add.request"
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442

    _msg_data_template = {
        "_type": "orchestrator.sessions.add.request"
    }


class MsgOrchestratorSessionsDelete(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: UI -> SO

    Description: Message for deleting a session to SO
    """
443

444
    routing_key = "control.orchestrator.sessions.delete.request"
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461

    _msg_data_template = {
        "_type": "orchestrator.sessions.delete.request"
    }


class MsgOrchestratorSessionsUpdate(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: UI -> SO

    Description: Message for updating a session from SO
    """

462
    routing_key = "control.orchestrator.sessions.update.request"
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
    _msg_data_template = {
        "_type": "orchestrator.sessions.update.request"
    }


class MsgOrchestratorTestsGet(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: UI -> SO

    Description: Message for getting tests from SO
    """
478
    routing_key = "control.orchestrator.tests.get.request"
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494

    _msg_data_template = {
        "_type": "orchestrator.tests.get.request"
    }


class MsgOrchestratorTestsGetContributorName(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: UI -> SO

    Description: Message for getting tests from SO with contributor and name
    """
495
    routing_key = "control.orchestrator.tests.get_contributor_name.request"
496
497
498
499
500
501

    _msg_data_template = {
        "_type": "orchestrator.tests.get_contributor_name.request"
    }


502
503
# # # # # # UI API messages # # # # # # # #

Federico Sismondi's avatar
Federico Sismondi committed
504
505
506
507
508
509
510
511
512
class MsgUiReply(Message):
    routing_key = "ui.user.all.reply"

    _msg_data_template = {
        "_type": "ui.message.type.to.be.deprecated",
        "fields": [
        ]
    }

513

514
515
516
517
518
519
520
521
522
523
class MsgUiRequestTextInput(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: TT -> UI

    Description: Message for requesting action or information to user
    """
524
    routing_key = "ui.user.all.request"
525
526

    _msg_data_template = {
527
        "_type": "ui.message.type.to.be.deprecated",
Federico Sismondi's avatar
Federico Sismondi committed
528
        "tags": [],
529
        "fields": [
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
            {
                "name": "input_name",
                "type": "text"
            },
        ]
    }


class MsgUiRequestConfirmationButton(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: TT -> UI

    Description: Message for requesting confirmation button
    """
    routing_key = "ui.user.all.request"

    _msg_data_template = {
551
        "_type": "ui.message.type.to.be.deprecated",
Federico Sismondi's avatar
Federico Sismondi committed
552
        "tags": [],
553
554
        "fields": [
            {
555
                "name": "test_button",
556
557
558
559
560
561
562
                "type": "button",
                "value": True
            },
        ]
    }


563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
class MsgUiRequestSessionConfiguration(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: TT -> UI

    Description: Message for requesting configuration message to UI
    """
    routing_key = "ui.core.session.configuration.get.request"

    _msg_data_template = {
        "_type": "ui.core.session.configuration.get.request",
    }


580
581
582
583
584
585
586
587
588
589
590
591
592
class MsgUiDisplay(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: TT -> UI

    Description: Message to display in user interface
    """
    routing_key = "ui.user.all.display"

    _msg_data_template = {
593
594
595
        "_type": "ui.message.type.to.be.deprecated",
        "level": None,
        "tags": [],
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
        "fields": [
            {
                "type": "p",
                "value": "Hello World!"
            },
        ]
    }


class MsgUiDisplayMarkdownText(Message):
    """
    Requirements: ...

    Type: Event

    Pub/Sub: TT -> UI

    Description: Message for displaying Mardown text to user interface
    """
    routing_key = "ui.user.all.display"

    _msg_data_template = {
618
        "_type": "ui.message.type.to.be.deprecated",
Federico Sismondi's avatar
Federico Sismondi committed
619
620
        "level": None,
        "tags": [],
621
622
623
624
625
        "fields": [
            {
                "type": "p",
                "value": "Hello World!"
            },
626
627
628
        ]
    }

629

630
# # # # # # AGENT MESSAGES # # # # # #
Federico Sismondi's avatar
Federico Sismondi committed
631

632

Federico Sismondi's avatar
Federico Sismondi committed
633
634
class MsgAgentTunStart(Message):
    """
635
    Requirements: Testing Tool MAY implement (if IP tun needed)
Federico Sismondi's avatar
Federico Sismondi committed
636

637
    Type: Event
Federico Sismondi's avatar
Federico Sismondi committed
638

639
    Pub/Sub: Testing Tool -> Agent
Federico Sismondi's avatar
Federico Sismondi committed
640

641
    Description: Message for triggering start IP tun interface in OS where the agent is running
Federico Sismondi's avatar
Federico Sismondi committed
642
    """
643
    routing_key = "control.tun.toAgent.agent_TT"
Federico Sismondi's avatar
Federico Sismondi committed
644
645

    _msg_data_template = {
646
647
648
649
        "_type": "tun.start",
        "name": "agent_TT",
        "ipv6_prefix": "bbbb",
        "ipv6_host": ":3",
650
        "ipv6_no_forwarding": False,
651
652
653
        "ipv4_host": None,
        "ipv4_network": None,
        "ipv4_netmask": None,
Federico Sismondi's avatar
Federico Sismondi committed
654
655
656
    }


657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
class MsgAgentSerialStarted(Message):
    """
    Description: Message for indicating that agent serial interface has been started

    Type: Event

    Pub/Sub: Testing Tool -> Agent

    Description: TBD
    """
    routing_key = "control.serial.from.tbd"

    _msg_data_template = {
        "_type": "serial.started",
        "name": "tbd",
        "port": "tbd",
        "boudrate": "tbd",
    }


Federico Sismondi's avatar
Federico Sismondi committed
677
678
class MsgAgentTunStarted(Message):
    """
679
    Description: Message for indicating that agent tun has been started
Federico Sismondi's avatar
Federico Sismondi committed
680

681
    Type: Event
Federico Sismondi's avatar
Federico Sismondi committed
682

683
    Pub/Sub: Agent -> Testing Tool
Federico Sismondi's avatar
Federico Sismondi committed
684

685
    Description: TBD
Federico Sismondi's avatar
Federico Sismondi committed
686
    """
687
    routing_key = "control.tun.from.tbd"
Federico Sismondi's avatar
Federico Sismondi committed
688
689

    _msg_data_template = {
690
691
692
693
694
695
696
        "_type": "tun.started",
        "name": "agent_TT",
        "ipv6_prefix": "bbbb",
        "ipv6_host": ":3",
        "ipv4_host": None,
        "ipv4_network": None,
        "ipv4_netmask": None,
697
        "ipv6_no_forwarding": False,
Federico Sismondi's avatar
Federico Sismondi committed
698
699
    }

700

701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
class MsgPacketInjectRaw(Message):
    """
    Description: Message to be captured by the agent an push into the correct embedded interface (e.g. tun, serial, etc..)

    Type: Event

    Pub/Sub: Testing Tool -> Agent

    Description: TBD
    """
    routing_key = None  # depends on the agent_id and the agent interface being used, re-write after creation

    _msg_data_template = {
        "_type": "packet.to_inject.raw",
        "timestamp": "1488586183.45",
        "interface_name": "tun0",
        "data": [96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0,
                 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 7, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0,
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]}


722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
class MsgPacketSniffedRaw(Message):
    """
    Description: Message captured by the agent in one of its embedded interfaces (e.g. tun, serial, etc..)

    Type: Event

    Pub/Sub: Agent -> Testing Tool

    Description: TBD
    """
    routing_key = None  # depends on the agent_id and the agent interface being used, re-write after creation

    _msg_data_template = {
        "_type": "packet.sniffed.raw",
        "timestamp": "1488586183.45",
        "interface_name": "tun0",
        "data": [96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0,
                 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 7, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0,
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]}
741

742
743

# # # # # # SESSION MESSAGES # # # # # #
744

745
class MsgTestingToolTerminate(Message):
746
    """
747
    Requirements: TT MUST listen to event, and handle a gracefully termination of all it's processes
Federico Sismondi's avatar
Federico Sismondi committed
748

749
    Type: Event
Federico Sismondi's avatar
Federico Sismondi committed
750

751
    Pub/Sub: GUI, (or Orchestrator) -> Testing Tool
Federico Sismondi's avatar
Federico Sismondi committed
752

753
    Description: Testing tool should stop all it's processes gracefully.
754
    """
755
    routing_key = "control.session"
756
757

    _msg_data_template = {
758
        "_type": "testingtool.terminate",
759
        "description": "Command TERMINATE testing tool execution"
760
761
762
763
764
    }


class MsgTestingToolReady(Message):
    """
765
    Requirements: TT MUST publish event as soon as TT is up and listening on the event bus
Federico Sismondi's avatar
Federico Sismondi committed
766

767
    Type: Event
Federico Sismondi's avatar
Federico Sismondi committed
768

769
    Pub/Sub: Testing Tool -> GUI
Federico Sismondi's avatar
Federico Sismondi committed
770

771
    Description: Used to indicate to the GUI that testing is ready to start the test suite
772
    """
773
    routing_key = "control.session"
774
775

    _msg_data_template = {
776
        "_type": "testingtool.ready",
777
        "description": "Testing tool READY to start test suite."
778
779
780
781
782
    }


class MsgTestingToolComponentReady(Message):
    """
783
    Requirements: Testing Tool SHOULD implement (other components should not subscribe to event)
Federico Sismondi's avatar
Federico Sismondi committed
784

785
    Type: Event
Federico Sismondi's avatar
Federico Sismondi committed
786

787
    Pub/Sub: Any Testing tool's component -> Test Coordinator
Federico Sismondi's avatar
Federico Sismondi committed
788

789
    Description: Once a testing tool's component is ready, it should publish a compoennt ready message
790
    """
791
    routing_key = "control.session"
792
793

    _msg_data_template = {
794
        "_type": "testingtool.component.ready",
795
        "component": "SomeComponent",
796
        "description": "Component READY to start test suite."
797
798
799
    }


800
801
802
803
804
805
806
807
808
809
class MsgSessionChat(Message):
    """
    Requirements: GUI should implement

    Type: Event

    Pub/Sub: UI 1 (2) -> UI 2 (1)

    Description: Generic descriptor of chat messages
    """
810
    routing_key = "control.session"
811
812
813
814

    _msg_data_template = {
        "_type": "chat",
        "user_name": "Ringo",
815
        "node": "tbd",
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
        "description": "I've got blisters on my fingers!"
    }


class MsgSessionLog(Message):
    """
    Requirements: Testing Tool SHOULD implement

    Type: Event

    Pub/Sub: Any Testing tool's component -> user/devs interfaces

    Description: Generic descriptor of log messages
    """
    routing_key = "log.warning.the_drummer"

    _msg_data_template = {
        "_type": "log",
Federico Sismondi's avatar
Federico Sismondi committed
834
        "component": "misc",
835
        "message": "I've got blisters on my fingers!"
836
837
838
    }


839
840
class MsgSessionConfiguration(Message):
    """
841
    Requirements: TT MUST listen to event, and configure accordingly
842
843
844
845
846

    Type: Event

    Pub/Sub: Orchestrator -> Testing Tool

847
    Description: TT MUST listen to this message and configure the testsuite correspondingly
848
849
    """
    routing_key = "control.session"
850

851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
    _msg_data_template = {
        "_type": "session.configuration",
        "session_id": "666",
        "configuration": {
            'testsuite.testcases': [
                'someTestCaseId1',
                'someTestCaseId2'
            ]
        },
        "testing_tools": "f-interop/someTestToolId",
        "users": [
            "u1",
            "f-interop"
        ],
    }


# TODO deprecate this in favor of the generic MsgSessionConfiguration
869
class MsgInteropSessionConfiguration(Message):
870
    """
871
    Requirements: TT MUST listen to event
Federico Sismondi's avatar
Federico Sismondi committed
872

873
    Type: Event
Federico Sismondi's avatar
Federico Sismondi committed
874

875
    Pub/Sub: Orchestrator -> Testing Tool
Federico Sismondi's avatar
Federico Sismondi committed
876

877
    Description: TT MUST listen to this message and configure the testsuite correspondingly
878
    """
879
    routing_key = "control.session"
880
881

    _msg_data_template = {
882
883
        "_type": "session.interop.configuration",
        "session_id": "TBD",
884
885
886
887
888
889
890
891
        "configuration":
            {
                'testsuite.testcases': [
                    'http://doc.f-interop.eu/tests/TD_COAP_CORE_01',
                    'http://doc.f-interop.eu/tests/TD_COAP'
                ]
            },

892
        "testing_tools": "f-interop/interoperability-coap",
893
        "users": [
894
895
896
            "u1",
            "f-interop"
        ],
897
        "tests": [
898
            {
Federico Sismondi's avatar
Federico Sismondi committed
899
                "testcase_ref": "http://doc.f-interop.eu/tests/TD_COAP_CORE_01",
900
                "settings": {}
901
902
            },
            {
Federico Sismondi's avatar
Federico Sismondi committed
903
                "testcase_ref": "http://doc.f-interop.eu/tests/TD_COAP_CORE_02",
904
905
906
                "settings": {}
            },
            {
Federico Sismondi's avatar
Federico Sismondi committed
907
                "testcase_ref": "http://doc.f-interop.eu/tests/TD_COAP_CORE_03",
908
                "settings": {}
909
910
911
912
913
            }
        ]
    }


914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
class MsgAgentConfigured(Message):
    """
    Requirements: Testing Tool SHOULD publish event

    Type: Event

    Pub/Sub: Testing Tool -> GUI

    Description: The goal is to notify GUI when agents are ready to start the session
    """

    routing_key = "control.session"

    _msg_data_template = {
        "_type": "agent.configured",
929
        "description": "Agent successfully CONFIGURED",
930
931
932
933
        'name': 'agent_TT'
    }


934
935
class MsgTestingToolConfigured(Message):
    """
936
    Requirements: TT MUST publish event once session.configuration message has been processed.
Federico Sismondi's avatar
Federico Sismondi committed
937

938
    Type: Event
Federico Sismondi's avatar
Federico Sismondi committed
939

940
    Pub/Sub: Testing Tool -> Orchestrator, GUI
Federico Sismondi's avatar
Federico Sismondi committed
941

942
    Description: The goal is to notify orchestrator and other components that the testing tool has been configured
943
944
945
946
947
    """

    routing_key = "control.session"

    _msg_data_template = {
948
        "_type": "testingtool.configured",
949
        "description": "Testing tool CONFIGURED",
950
        "session_id": "TBD",
951
952
953
        "testing_tools": "f-interop/interoperability-coap",
    }

954

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
class MsgSessionCreated(Message):
    """
    Requirements: Session Orchestrator MUST publish message on common-services channel (on every session creation)

    Type: Event

    Pub/Sub: SO -> viz tools

    Description: The goal is to notify viz tools about new sessions
    """

    routing_key = "control.session.created"

    _msg_data_template = {
        "_type": "session.created",
        "description": "A new session has been created",
        "session_id": "TBD",
        "testing_tools": "TBD",
    }


976
977
class MsgTestingToolComponentShutdown(Message):
    """
978
    Requirements: Testing Tool SHOULD implement (other components should not subscribe to event)
Federico Sismondi's avatar
Federico Sismondi committed
979

980
    Type: Event
Federico Sismondi's avatar
Federico Sismondi committed
981

982
    Pub/Sub: Any Testing tool's component -> Test Coordinator
Federico Sismondi's avatar
Federico Sismondi committed
983

984
985
    Description: tbd
    """
986
987
988
    routing_key = "control.session"

    _msg_data_template = {
989
        "_type": "testingtool.component.shutdown",
990
        "component": "SomeComponent",
991
        "description": "Component SHUTDOWN. Bye!"
992
993
    }

994
    # # # # # # TEST COORDINATION MESSAGES # # # # # #
995

996
997
998

class MsgTestSuiteStart(Message):
    """
999
    Requirements: TT MUST listen to event and start the test suite right after reception. MsgTestSuiteStarted
Federico Sismondi's avatar
Federico Sismondi committed
1000

1001
    Type: Event
Federico Sismondi's avatar
Federico Sismondi committed
1002

1003
    Pub/Sub: GUI -> Testing Tool
Federico Sismondi's avatar
Federico Sismondi committed
1004

1005
    Description: tbd
1006
1007
    """

1008
    # TODO change to control.testsuite
1009
    routing_key = "control.testcoordination"
1010
1011

    _msg_data_template = {
1012
        "_type": "testcoordination.testsuite.start",
1013
        "description": "Test suite START command"
1014
1015
    }

1016

Federico Sismondi's avatar
Federico Sismondi committed
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
class MsgTestSuiteStarted(Message):
    """
    Requirements: Testing Tool SHOULD publish to event

    Type: Event

    Pub/Sub: Testing Tool -> GUI

    Description: tbd
    """

1028
    # TODO change to control.testsuite
Federico Sismondi's avatar
Federico Sismondi committed
1029
1030
1031
1032
    routing_key = "control.testcoordination"

    _msg_data_template = {
        "_type": "testcoordination.testsuite.started",
1033
        "description": "Test suite STARTED"
Federico Sismondi's avatar
Federico Sismondi committed
1034
    }
1035

1036

1037
1038
class MsgTestSuiteFinish(Message):
    """
1039
    Requirements: TT MUST listen to event
Federico Sismondi's avatar
Federico Sismondi committed
1040

1041
    Type: Event
Federico Sismondi's avatar
Federico Sismondi committed
1042

1043
    Pub/Sub: GUI -> Testing Tool
Federico Sismondi's avatar
Federico Sismondi committed
1044

1045
    Description: tbd
1046
1047
    """

1048
    # TODO change to control.testsuite
1049
1050
1051
    routing_key = "control.testcoordination"

    _msg_data_template = {
1052
        "_type": "testcoordination.testsuite.finish",
1053
        "description": "Test suite FINISH command"
1054
1055
    }

1056

1057
1058
class MsgTestCaseReady(Message):
    """
1059
    Requirements: TT MUST publish event
Federico Sismondi's avatar
Federico Sismondi committed
1060

1061
    Type: Event
Federico Sismondi's avatar
Federico Sismondi committed
1062

Federico Sismondi's avatar
Federico Sismondi committed
1063
    Pub/Sub: Testing Tool -> GUI
Federico Sismondi's avatar
Federico Sismondi committed
1064

1065
1066
1067
    Description:
        - Used to indicate to the GUI (or automated-iut) which is the next test case to be executed.
        - This message is normally followed by a MsgTestCaseStart (from GUI-> Testing Tool)
1068
1069
    """

1070
    # TODO change to control.testsuite
1071
    routing_key = "control.testcoordination"
1072
1073

    _msg_data_template = {
1074
        "_type": "testcoordination.testcase.ready",
Federico Sismondi's avatar
Federico Sismondi committed
1075
1076
1077
        "description": "Next test case to be executed is TD_COAP_CORE_01",
        "testcase_id": "TD_COAP_CORE_01",
        "testcase_ref": "http://doc.f-interop.eu/tests/TD_COAP_CORE_01",
1078
1079
        "objective": "Perform GET transaction(CON mode)",
        "state": None
1080
1081
1082
    }


1083
1084
class MsgTestCaseStart(Message):
    """
1085
    Requirements: TT MUST listen to event
Federico Sismondi's avatar
Federico Sismondi committed
1086

1087
    Type: Event
Federico Sismondi's avatar
Federico Sismondi committed
1088

1089
    Pub/Sub: GUI -> Testing Tool
Federico Sismondi's avatar
Federico Sismondi committed
1090

1091
1092
    Description:
        - Message used for indicating the testing tool to start the test case (the one previously selected)
1093
1094
        - if testcase_id is Null then testing tool starts previously announced testcase in message
        "testcoordination.testcase.ready",
1095
    """
1096
    # TODO change to control.testsuite
1097
    routing_key = "control.testcoordination"
1098
1099

    _msg_data_template = {
1100
        "_type": "testcoordination.testcase.start",
1101
        "description": "Test case START command",
Federico Sismondi's avatar
Federico Sismondi committed
1102
        "testcase_id": None,
1103
1104
    }

Federico Sismondi's avatar
Federico Sismondi committed
1105

1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
class MsgTestCaseStarted(Message):
    """
    Requirements: Testing Tool SHOULD publish event

    Type: Event

    Pub/Sub: Testing Tool -> GUI

    Description:
        - Message used for indicating that testcase has started
    """
1117
    # TODO change to control.testsuite
1118
1119
1120
1121
    routing_key = "control.testcoordination"

    _msg_data_template = {
        "_type": "testcoordination.testcase.started",
1122
        "description": "Test case STARTED",
1123
1124
        "testcase_id": "TBD",
    }
1125

Federico Sismondi's avatar
Federico Sismondi committed
1126

1127
1128
# TODO MsgTestCaseNotes, see https://portal.etsi.org/cti/downloads/TestSpecifications/6LoWPAN_Plugtests_TestDescriptions_1.0.pdf

1129

1130
1131
class MsgTestCaseConfiguration(Message):
    """
1132
    Requirements: Testing Tool MAY publish event (if needed for executing the test case)
1133
1134
1135
1136
1137
1138
    Type: Event
    Pub/Sub: Testing Tool -> GUI & automated-iut
    Description:
        - Message used to indicate GUI and/or automated-iut which configuration to use.
        - IMPORTANT: deprecate this message in favor of MsgConfigurationExecute and MsgConfigurationExecuted
    """
1139
1140

    # TODO change to control.testsuite