diff --git a/awx/network_ui/admin.py b/awx/network_ui/admin.py index 0f5abc13b2..b79cbe2ecb 100644 --- a/awx/network_ui/admin.py +++ b/awx/network_ui/admin.py @@ -1,4 +1,3 @@ -# Copyright (c) 2017 Red Hat, Inc from django.contrib import admin from awx.network_ui.models import Device @@ -33,6 +32,8 @@ from awx.network_ui.models import Toolbox from awx.network_ui.models import ToolboxItem +from awx.network_ui.models import FSMTrace + class DeviceAdmin(admin.ModelAdmin): fields = ('topology', 'name', 'x', 'y', 'id', 'type', 'interface_id_seq', 'process_id_seq',) @@ -160,3 +161,11 @@ class ToolboxItemAdmin(admin.ModelAdmin): admin.site.register(ToolboxItem, ToolboxItemAdmin) + + +class FSMTraceAdmin(admin.ModelAdmin): + fields = ('fsm_name', 'from_state', 'to_state', 'message_type', 'client', 'trace_session_id', 'order',) + raw_id_fields = ('client',) + + +admin.site.register(FSMTrace, FSMTraceAdmin) diff --git a/awx/network_ui/consumers.py b/awx/network_ui/consumers.py index e15689f865..51151be65c 100644 --- a/awx/network_ui/consumers.py +++ b/awx/network_ui/consumers.py @@ -8,6 +8,7 @@ from awx.network_ui.models import GroupDevice as GroupDeviceMap from awx.network_ui.models import DataSheet, DataBinding, DataType from awx.network_ui.models import Process, Stream from awx.network_ui.models import Toolbox, ToolboxItem +from awx.network_ui.models import FSMTrace from awx.network_ui.serializers import yaml_serialize_topology from awx.network_ui.messages import MultipleMessage, InterfaceCreate, LinkCreate, to_dict import urlparse @@ -262,12 +263,16 @@ class _Persistence(object): print "no sender" return if isinstance(data[1], dict) and client_id != data[1].get('sender'): - logger.error("client_id mismatch expected:", client_id, "actual:", data[1].get('sender')) + logger.error("client_id mismatch expected: %s actual %s", client_id, data[1].get('sender')) logger.error(pformat(data)) return message_type = data[0] message_value = data[1] - message_type_id = MessageType.objects.get_or_create(name=message_type)[0].pk + try: + message_type_id = MessageType.objects.get(name=message_type).pk + except ObjectDoesNotExist, e: + logger.warning("Unsupported message %s", message_type) + return TopologyHistory(topology_id=topology_id, client_id=client_id, message_type_id=message_type_id, @@ -510,6 +515,15 @@ class _Persistence(object): if new_entries: GroupDeviceMap.objects.bulk_create(new_entries) + def onFSMTrace(self, message_value, diagram_id, client_id): + FSMTrace(trace_session_id=message_value['trace_id'], + fsm_name=message_value['fsm_name'], + from_state=message_value['from_state'], + to_state=message_value['to_state'], + order=message_value['order'], + client_id=client_id, + message_type=message_value['recv_message_type'] or "none").save() + persistence = _Persistence() diff --git a/awx/network_ui/designs/models.yml b/awx/network_ui/designs/models.yml index aefebe8483..e0d6303b50 100644 --- a/awx/network_ui/designs/models.yml +++ b/awx/network_ui/designs/models.yml @@ -99,8 +99,8 @@ models: pk: true type: AutoField name: Client - x: -455 - y: 109 + x: -510 + y: 141 - fields: - name: topology_history_id pk: true @@ -136,8 +136,8 @@ models: name: name type: CharField name: MessageType - x: -509 - y: 383 + x: -501 + y: 428 - display: name fields: - name: interface_id @@ -305,8 +305,8 @@ models: name: name type: CharField name: Toolbox - x: -222 - y: 627 + x: 179 + y: 644 - fields: - name: toolbox_item_id pk: true @@ -318,8 +318,37 @@ models: - name: data type: TextField name: ToolboxItem - x: 54 - y: 664 + x: 391 + y: 645 +- fields: + - name: fsm_trace_id + pk: true + type: AutoField + - len: 200 + name: fsm_name + type: CharField + - len: 200 + name: from_state + type: CharField + - len: 200 + name: to_state + type: CharField + - len: 200 + name: message_type + type: CharField + - name: client + ref: Client + ref_field: client_id + type: ForeignKey + - default: 0 + name: trace_session_id + type: IntegerField + - default: 0 + name: order + type: IntegerField + name: FSMTrace + x: -872 + y: 507 modules: [] view: panX: 213.72955551921206 diff --git a/awx/network_ui/migrations/0022_fsmtrace.py b/awx/network_ui/migrations/0022_fsmtrace.py new file mode 100644 index 0000000000..2f72ef79f3 --- /dev/null +++ b/awx/network_ui/migrations/0022_fsmtrace.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('network_ui', '0021_toolbox_toolboxitem'), + ] + + operations = [ + migrations.CreateModel( + name='FSMTrace', + fields=[ + ('fsm_trace_id', models.AutoField(serialize=False, primary_key=True)), + ('fsm_name', models.CharField(max_length=200)), + ('from_state', models.CharField(max_length=200)), + ('to_state', models.CharField(max_length=200)), + ('message_type', models.CharField(max_length=200)), + ('trace_session_id', models.IntegerField(default=0)), + ('order', models.IntegerField(default=0)), + ('client', models.ForeignKey(to='network_ui.Client')), + ], + ), + ] diff --git a/awx/network_ui/migrations/0023_auto_20171213_1623.py b/awx/network_ui/migrations/0023_auto_20171213_1623.py new file mode 100644 index 0000000000..892e1be9ad --- /dev/null +++ b/awx/network_ui/migrations/0023_auto_20171213_1623.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations + +import yaml + +messages = yaml.load(''' +messages: + - {msg_type: DeviceMove, fields: [msg_type, sender, id, x, y, previous_x, previous_y]} + - {msg_type: DeviceCreate, fields: [msg_type, sender, id, x, y, name, type]} + - {msg_type: DeviceDestroy, fields: [msg_type, sender, id, previous_x, previous_y, previous_name, previous_type]} + - {msg_type: DeviceLabelEdit, fields: [msg_type, sender, id, name, previous_name]} + - {msg_type: DeviceSelected, fields: [msg_type, sender, id]} + - {msg_type: DeviceUnSelected, fields: [msg_type, sender, id]} + - {msg_type: InterfaceCreate, fields: [msg_type, sender, device_id, id, name]} + - {msg_type: InterfaceLabelEdit, fields: [msg_type, sender, id, device_id, name, previous_name]} + - {msg_type: LinkLabelEdit, fields: [msg_type, sender, id, name, previous_name]} + - {msg_type: LinkCreate, fields: [msg_type, id, sender, name, from_device_id, to_device_id, from_interface_id, to_interface_id]} + - {msg_type: LinkDestroy, fields: [msg_type, id, sender, name, from_device_id, to_device_id, from_interface_id, to_interface_id]} + - {msg_type: LinkSelected, fields: [msg_type, sender, id]} + - {msg_type: LinkUnSelected, fields: [msg_type, sender, id]} + - {msg_type: Undo, fields: [msg_type, sender, original_message]} + - {msg_type: Redo, fields: [msg_type, sender, original_message]} + - {msg_type: Deploy, fields: [msg_type, sender]} + - {msg_type: Destroy, fields: [msg_type, sender]} + - {msg_type: Discover, fields: [msg_type, sender]} + - {msg_type: Layout, fields: [msg_type, sender]} + - {msg_type: MultipleMessage, fields: [msg_type, sender, messages]} + - {msg_type: Coverage, fields: [msg_type, sender, coverage]} + - {msg_type: MouseEvent, fields: [msg_type, sender, x, y, type]} + - {msg_type: MouseWheelEvent, fields: [msg_type, sender, delta, deltaX, deltaY, type, originalEvent]} + - {msg_type: KeyEvent, fields: [msg_type, sender, key, keyCode, type, altKey, shiftKey, ctrlKey, metaKey]} + - {msg_type: TouchEvent, fields: [msg_type, sender, type, touches]} + - {msg_type: StartRecording, fields: [msg_type, sender]} + - {msg_type: StopRecording, fields: [msg_type, sender]} + - {msg_type: ViewPort, fields: [msg_type, sender, scale, panX, panY]} + - {msg_type: CopySite, fields: [msg_type, site]} + - {msg_type: GroupMove, fields: [msg_type, sender, id, x1, y1, x2, y2, previous_x1, previous_y1, previous_x2, previous_y2]} + - {msg_type: GroupCreate, fields: [msg_type, sender, id, x1, y1, x2, y2, name, type]} + - {msg_type: GroupDestroy, fields: [msg_type, sender, id, previous_x1, previous_y1, previous_x2, previous_y2, previous_name, previous_type]} + - {msg_type: GroupLabelEdit, fields: [msg_type, sender, id, name, previous_name]} + - {msg_type: GroupSelected, fields: [msg_type, sender, id]} + - {msg_type: GroupUnSelected, fields: [msg_type, sender, id]} + - {msg_type: GroupMembership, fields: [msg_type, sender, id, members]} + - {msg_type: TableCellEdit, fields: [msg_type, sender, sheet, col, row, old_value, new_value]} + - {msg_type: ProcessCreate, fields: [msg_type, id, name, type, device_id, x, y]} + - {msg_type: StreamCreate, fields: [msg_type, sender, id, from_id, to_id, label]} + - {msg_type: StreamDestroy, fields: [msg_type, sender, id, from_id, to_id, label]} + - {msg_type: StreamLabelEdit, fields: [msg_type, sender, id, label, previous_label]} + - {msg_type: StreamSelected, fields: [msg_type, sender, id]} + - {msg_type: StreamUnSelected, fields: [msg_type, sender, id]} +''') + + +def populate_message_types(apps, schema_editor): + + MessageType = apps.get_model('network_ui', 'MessageType') + for message in messages['messages']: + MessageType.objects.get_or_create(name=message['msg_type']) + + +class Migration(migrations.Migration): + + dependencies = [ + ('network_ui', '0022_fsmtrace'), + ] + + operations = [ + migrations.RunPython( + code=populate_message_types, + ), + ] diff --git a/awx/network_ui/migrations/0024_auto_20171213_1949.py b/awx/network_ui/migrations/0024_auto_20171213_1949.py new file mode 100644 index 0000000000..6b1f08eb65 --- /dev/null +++ b/awx/network_ui/migrations/0024_auto_20171213_1949.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations + +import yaml + +messages = yaml.load(''' +messages: + - {msg_type: DeviceMove, fields: [msg_type, sender, id, x, y, previous_x, previous_y]} + - {msg_type: DeviceCreate, fields: [msg_type, sender, id, x, y, name, type]} + - {msg_type: DeviceDestroy, fields: [msg_type, sender, id, previous_x, previous_y, previous_name, previous_type]} + - {msg_type: DeviceLabelEdit, fields: [msg_type, sender, id, name, previous_name]} + - {msg_type: DeviceSelected, fields: [msg_type, sender, id]} + - {msg_type: DeviceUnSelected, fields: [msg_type, sender, id]} + - {msg_type: InterfaceCreate, fields: [msg_type, sender, device_id, id, name]} + - {msg_type: InterfaceLabelEdit, fields: [msg_type, sender, id, device_id, name, previous_name]} + - {msg_type: LinkLabelEdit, fields: [msg_type, sender, id, name, previous_name]} + - {msg_type: LinkCreate, fields: [msg_type, id, sender, name, from_device_id, to_device_id, from_interface_id, to_interface_id]} + - {msg_type: LinkDestroy, fields: [msg_type, id, sender, name, from_device_id, to_device_id, from_interface_id, to_interface_id]} + - {msg_type: LinkSelected, fields: [msg_type, sender, id]} + - {msg_type: LinkUnSelected, fields: [msg_type, sender, id]} + - {msg_type: Undo, fields: [msg_type, sender, original_message]} + - {msg_type: Redo, fields: [msg_type, sender, original_message]} + - {msg_type: Deploy, fields: [msg_type, sender]} + - {msg_type: Destroy, fields: [msg_type, sender]} + - {msg_type: Discover, fields: [msg_type, sender]} + - {msg_type: Layout, fields: [msg_type, sender]} + - {msg_type: MultipleMessage, fields: [msg_type, sender, messages]} + - {msg_type: Coverage, fields: [msg_type, sender, coverage]} + - {msg_type: MouseEvent, fields: [msg_type, sender, x, y, type]} + - {msg_type: MouseWheelEvent, fields: [msg_type, sender, delta, deltaX, deltaY, type, originalEvent]} + - {msg_type: KeyEvent, fields: [msg_type, sender, key, keyCode, type, altKey, shiftKey, ctrlKey, metaKey]} + - {msg_type: TouchEvent, fields: [msg_type, sender, type, touches]} + - {msg_type: StartRecording, fields: [msg_type, sender]} + - {msg_type: StopRecording, fields: [msg_type, sender]} + - {msg_type: ViewPort, fields: [msg_type, sender, scale, panX, panY]} + - {msg_type: CopySite, fields: [msg_type, site]} + - {msg_type: GroupMove, fields: [msg_type, sender, id, x1, y1, x2, y2, previous_x1, previous_y1, previous_x2, previous_y2]} + - {msg_type: GroupCreate, fields: [msg_type, sender, id, x1, y1, x2, y2, name, type]} + - {msg_type: GroupDestroy, fields: [msg_type, sender, id, previous_x1, previous_y1, previous_x2, previous_y2, previous_name, previous_type]} + - {msg_type: GroupLabelEdit, fields: [msg_type, sender, id, name, previous_name]} + - {msg_type: GroupSelected, fields: [msg_type, sender, id]} + - {msg_type: GroupUnSelected, fields: [msg_type, sender, id]} + - {msg_type: GroupMembership, fields: [msg_type, sender, id, members]} + - {msg_type: TableCellEdit, fields: [msg_type, sender, sheet, col, row, old_value, new_value]} + - {msg_type: ProcessCreate, fields: [msg_type, id, name, type, device_id, x, y]} + - {msg_type: StreamCreate, fields: [msg_type, sender, id, from_id, to_id, label]} + - {msg_type: StreamDestroy, fields: [msg_type, sender, id, from_id, to_id, label]} + - {msg_type: StreamLabelEdit, fields: [msg_type, sender, id, label, previous_label]} + - {msg_type: StreamSelected, fields: [msg_type, sender, id]} + - {msg_type: StreamUnSelected, fields: [msg_type, sender, id]} + - {msg_type: FSMTrace, fields: [msg_type, order, sender, trace_id, fsm_name, from_state, to_state, recv_message_type]} + - {msg_type: ChannelTrace, fields: [msg_type, sender, trace_id, from_fsm, to_fsm, sent_message_type]} + + ''') + + +def populate_message_types(apps, schema_editor): + + MessageType = apps.get_model('network_ui', 'MessageType') + for message in messages['messages']: + MessageType.objects.get_or_create(name=message['msg_type']) + + +class Migration(migrations.Migration): + + dependencies = [ + ('network_ui', '0023_auto_20171213_1623'), + ] + + operations = [ + migrations.RunPython( + code=populate_message_types, + ), + ] diff --git a/awx/network_ui/models.py b/awx/network_ui/models.py index 9c538fb450..e454c88a3d 100644 --- a/awx/network_ui/models.py +++ b/awx/network_ui/models.py @@ -156,3 +156,15 @@ class ToolboxItem(models.Model): toolbox_item_id = models.AutoField(primary_key=True,) toolbox = models.ForeignKey('Toolbox',) data = models.TextField() + + +class FSMTrace(models.Model): + + fsm_trace_id = models.AutoField(primary_key=True,) + fsm_name = models.CharField(max_length=200,) + from_state = models.CharField(max_length=200,) + to_state = models.CharField(max_length=200,) + message_type = models.CharField(max_length=200,) + client = models.ForeignKey('Client',) + trace_session_id = models.IntegerField(default=0) + order = models.IntegerField(default=0) diff --git a/awx/network_ui/static/network_ui/CONTRIBUTING.md b/awx/network_ui/static/network_ui/CONTRIBUTING.md index d466999583..45b3eb5de8 100644 --- a/awx/network_ui/static/network_ui/CONTRIBUTING.md +++ b/awx/network_ui/static/network_ui/CONTRIBUTING.md @@ -571,11 +571,11 @@ The messages defined are [src/messages.js](src/messages.js): **Message Passing** -Messages are passed along channels between FSMs and over the websocket to and from the -server. Messages from the server over the web socket and user input events from the web -browser are passed to the `first_controller` where they are handled and discarded or -passed along the chain of FSMControllers until they reach the end with `null_controller` -or they are handled and the models are updated. +Messages are passed along channels between FSMs and over the websocket to and +from the server. Messages from the server over the web socket and user input +events from the web browser are passed to the `first_channel` where they are +passed along the chain of FSMControllers until they reach the end with +`NullChannel` or they are handled and the models are updated. * See: [src/network.ui.controller.js](src/network.ui.controller.js#L115) diff --git a/awx/network_ui/static/network_ui/Makefile b/awx/network_ui/static/network_ui/Makefile index 4ef346b42f..df9deb6ef1 100644 --- a/awx/network_ui/static/network_ui/Makefile +++ b/awx/network_ui/static/network_ui/Makefile @@ -29,7 +29,7 @@ istanbul: main simple-server: lint main lessc - python -m SimpleHTTPServer 8081 + python -m SimpleHTTPServer 8082 deploy: main diff --git a/awx/network_ui/static/network_ui/designs/button.yml b/awx/network_ui/static/network_ui/designs/button.yml index 7441dc345e..868def3e9a 100644 --- a/awx/network_ui/static/network_ui/designs/button.yml +++ b/awx/network_ui/static/network_ui/designs/button.yml @@ -1,4 +1,4 @@ -app: button +app: button_fsm panX: 53 panY: -52 scaleXY: 1 diff --git a/awx/network_ui/static/network_ui/designs/buttons.yml b/awx/network_ui/static/network_ui/designs/buttons.yml index a0efa20d36..4a9a323b49 100644 --- a/awx/network_ui/static/network_ui/designs/buttons.yml +++ b/awx/network_ui/static/network_ui/designs/buttons.yml @@ -1,4 +1,4 @@ -app: buttons +app: buttons_fsm panX: 133 panY: 41 scaleXY: 1 diff --git a/awx/network_ui/static/network_ui/designs/device_detail.yml b/awx/network_ui/static/network_ui/designs/device_detail.yml index 810655123e..b2cc6ee5da 100644 --- a/awx/network_ui/static/network_ui/designs/device_detail.yml +++ b/awx/network_ui/static/network_ui/designs/device_detail.yml @@ -1,5 +1,5 @@ finite_state_machine_id: 131 -name: fsm +name: device_detail_fsm states: - id: 2 label: Ready diff --git a/awx/network_ui/static/network_ui/designs/group.yml b/awx/network_ui/static/network_ui/designs/group.yml index 3c36f739c4..dbb4fe7ae6 100644 --- a/awx/network_ui/static/network_ui/designs/group.yml +++ b/awx/network_ui/static/network_ui/designs/group.yml @@ -1,57 +1,57 @@ -finite_state_machine_id: 6 -name: fsm +diagram_id: 38 +name: group_fsm states: -- id: 11 +- id: 1 label: Disable x: 497 y: 84 -- id: 1 +- id: 2 label: Resize x: 571 y: 911 -- id: 2 +- id: 3 label: Start x: 744 y: 69 -- id: 3 - label: CornerSelected - x: 359 - y: 682 -- id: 4 +- id: 5 label: Selected1 x: 839 y: 640 -- id: 5 +- id: 6 label: Selected3 x: 1528 y: 360 -- id: 6 +- id: 7 label: Move x: 1297 y: 786 -- id: 9 +- id: 8 label: Selected2 x: 1179 y: 435 - id: 10 - label: Placing - x: 410 - y: 295 -- id: 7 label: Ready x: 733 y: 304 -- id: 8 +- id: 11 label: EditLabel x: 1130 y: 112 +- id: 4 + label: CornerSelected + x: 526 + y: 554 +- id: 9 + label: Placing + x: 299 + y: 300 transitions: - from_state: CornerSelected label: onMouseMove to_state: Resize - from_state: Placing label: onMouseDown - to_state: CornerSelected + to_state: Resize - from_state: Ready label: onMouseDown to_state: CornerSelected diff --git a/awx/network_ui/static/network_ui/designs/hotkeys.yml b/awx/network_ui/static/network_ui/designs/hotkeys.yml index 95fd1d3982..f499511440 100644 --- a/awx/network_ui/static/network_ui/designs/hotkeys.yml +++ b/awx/network_ui/static/network_ui/designs/hotkeys.yml @@ -1,5 +1,5 @@ finite_state_machine_id: 113 -name: hotkeys +name: hotkeys_fsm states: - id: 2 label: Enabled diff --git a/awx/network_ui/static/network_ui/designs/link.yml b/awx/network_ui/static/network_ui/designs/link.yml index f5227f500f..a9fb63ae8a 100644 --- a/awx/network_ui/static/network_ui/designs/link.yml +++ b/awx/network_ui/static/network_ui/designs/link.yml @@ -1,5 +1,5 @@ finite_state_machine_id: 10 -name: src/link +name: link_fsm states: - id: 5 label: Selecting diff --git a/awx/network_ui/static/network_ui/designs/messages.yml b/awx/network_ui/static/network_ui/designs/messages.yml index ad58b27dd5..92813cb71e 100644 --- a/awx/network_ui/static/network_ui/designs/messages.yml +++ b/awx/network_ui/static/network_ui/designs/messages.yml @@ -42,4 +42,6 @@ messages: - {msg_type: StreamLabelEdit, fields: [msg_type, sender, id, label, previous_label]} - {msg_type: StreamSelected, fields: [msg_type, sender, id]} - {msg_type: StreamUnSelected, fields: [msg_type, sender, id]} + - {msg_type: FSMTrace, fields: [msg_type, order, sender, trace_id, fsm_name, from_state, to_state, recv_message_type]} + - {msg_type: ChannelTrace, fields: [msg_type, sender, trace_id, from_fsm, to_fsm, sent_message_type]} diff --git a/awx/network_ui/static/network_ui/designs/mode.yml b/awx/network_ui/static/network_ui/designs/mode.yml index 8a2a17c1d6..49c5f5952f 100644 --- a/awx/network_ui/static/network_ui/designs/mode.yml +++ b/awx/network_ui/static/network_ui/designs/mode.yml @@ -1,5 +1,5 @@ finite_state_machine_id: 130 -name: mode +name: mode_fsm states: - id: 1 label: Start diff --git a/awx/network_ui/static/network_ui/designs/move.yml b/awx/network_ui/static/network_ui/designs/move.yml index bc6d55ebfb..03d83d72bf 100644 --- a/awx/network_ui/static/network_ui/designs/move.yml +++ b/awx/network_ui/static/network_ui/designs/move.yml @@ -1,5 +1,5 @@ finite_state_machine_id: 13 -name: move +name: move_fsm states: - id: 9 label: Disable diff --git a/awx/network_ui/static/network_ui/designs/null.yml b/awx/network_ui/static/network_ui/designs/null.yml index d8e3e8dd06..6cc188b4a5 100644 --- a/awx/network_ui/static/network_ui/designs/null.yml +++ b/awx/network_ui/static/network_ui/designs/null.yml @@ -1,5 +1,5 @@ finite_state_machine_id: 114 -name: fsm +name: null_fsm states: - id: 1 label: Start diff --git a/awx/network_ui/static/network_ui/designs/rack.yml b/awx/network_ui/static/network_ui/designs/rack.yml index 9ea4bbd27c..d9bffb9cf9 100644 --- a/awx/network_ui/static/network_ui/designs/rack.yml +++ b/awx/network_ui/static/network_ui/designs/rack.yml @@ -1,5 +1,5 @@ finite_state_machine_id: 131 -name: fsm +name: rack_fsm states: - id: 5 label: Selected2 diff --git a/awx/network_ui/static/network_ui/designs/site.yml b/awx/network_ui/static/network_ui/designs/site.yml index 9ea4bbd27c..cb813aab5e 100644 --- a/awx/network_ui/static/network_ui/designs/site.yml +++ b/awx/network_ui/static/network_ui/designs/site.yml @@ -1,5 +1,5 @@ finite_state_machine_id: 131 -name: fsm +name: site_fsm states: - id: 5 label: Selected2 diff --git a/awx/network_ui/static/network_ui/designs/stream.yml b/awx/network_ui/static/network_ui/designs/stream.yml index bb832259b1..c0a1bc1aa7 100644 --- a/awx/network_ui/static/network_ui/designs/stream.yml +++ b/awx/network_ui/static/network_ui/designs/stream.yml @@ -1,5 +1,5 @@ finite_state_machine_id: 82 -name: src/transition +name: stream_fsm states: - id: 4 label: Connecting diff --git a/awx/network_ui/static/network_ui/designs/time.yml b/awx/network_ui/static/network_ui/designs/time.yml index 5ef3634919..8d731b155d 100644 --- a/awx/network_ui/static/network_ui/designs/time.yml +++ b/awx/network_ui/static/network_ui/designs/time.yml @@ -1,5 +1,5 @@ finite_state_machine_id: 11 -name: src/time +name: time_fsm states: - id: 1 label: Present diff --git a/awx/network_ui/static/network_ui/designs/toolbox.yml b/awx/network_ui/static/network_ui/designs/toolbox.yml index e62e5f502d..99fd550b54 100644 --- a/awx/network_ui/static/network_ui/designs/toolbox.yml +++ b/awx/network_ui/static/network_ui/designs/toolbox.yml @@ -1,5 +1,5 @@ -finite_state_machine_id: 24 -name: toolbox +finite_state_machine_id: 14 +name: toolbox_fsm states: - id: 9 label: Disabled diff --git a/awx/network_ui/static/network_ui/designs/view.yml b/awx/network_ui/static/network_ui/designs/view.yml index ee889f5a3e..e06df0cb22 100644 --- a/awx/network_ui/static/network_ui/designs/view.yml +++ b/awx/network_ui/static/network_ui/designs/view.yml @@ -1,5 +1,5 @@ finite_state_machine_id: 15 -name: view +name: view_fsm states: - id: 1 label: Start diff --git a/awx/network_ui/static/network_ui/src/buttons.js b/awx/network_ui/static/network_ui/src/buttons.js index fc0f4e5a50..635b207e78 100644 --- a/awx/network_ui/static/network_ui/src/buttons.js +++ b/awx/network_ui/static/network_ui/src/buttons.js @@ -46,7 +46,7 @@ _Ready.prototype.onMouseDown = function (controller, msg_type, $event) { button = null; } if (button === null) { - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); } }; @@ -70,7 +70,7 @@ _Ready.prototype.onMouseMove = function (controller, msg_type, $event) { } } - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; diff --git a/awx/network_ui/static/network_ui/src/fsm.js b/awx/network_ui/static/network_ui/src/fsm.js index e7692e1a80..4c04dfa971 100644 --- a/awx/network_ui/static/network_ui/src/fsm.js +++ b/awx/network_ui/static/network_ui/src/fsm.js @@ -1,38 +1,89 @@ /* Copyright (c) 2017 Red Hat, Inc. */ -function FSMController (scope, initial_state, next_controller, name) { +var messages = require('./messages.js'); + +function Channel(from_controller, to_controller, tracer) { + this.tracer = tracer; + this.from_controller = from_controller; + this.to_controller = to_controller; + this.trace = false; +} +exports.Channel = Channel; + +Channel.prototype.send = function(msg_type, message) { + if (this.trace && this.from_controller !== null) { + this.tracer.send_trace_message(new messages.ChannelTrace(this.from_controller.name, + this.to_controller.name, + msg_type)); + } + this.to_controller.handle_message(msg_type, message); +}; + +function NullChannel(from_controller, tracer) { + this.tracer = tracer; + this.from_controller = from_controller; + this.trace = false; +} + +NullChannel.prototype.send = function(msg_type) { + if (this.trace) { + this.tracer.send_trace_message(new messages.ChannelTrace(this.from_controller.name, + 'null', + msg_type)); + } +}; + +function FSMController (scope, name, initial_state, tracer) { this.scope = scope; - this.state = initial_state; - this.next_controller = next_controller; this.name = name; - this.debug = false; + this.state = initial_state; + this.delegate_channel = new NullChannel(this, tracer); + this.tracer = tracer; + this.trace = true; + this.handling_message_type = 'start'; this.state.start(this); + this.handling_message_type = null; } exports.FSMController = FSMController; FSMController.prototype.changeState = function (state) { + var old_handling_message_type; if(this.state !== null) { + old_handling_message_type = this.handling_message_type; + this.handling_message_type = 'end'; this.state.end(this); + this.handling_message_type = old_handling_message_type; + } + if (this.trace) { + this.tracer.send_trace_message(new messages.FSMTrace(this.tracer.trace_order_seq(), + this.name, + this.state.name, + state.name, + this.handling_message_type)); } this.state = state; if(state !== null) { + old_handling_message_type = this.handling_message_type; + this.handling_message_type = 'start'; state.start(this); + this.handling_message_type = old_handling_message_type; } }; FSMController.prototype.handle_message = function(msg_type, message) { + var old_handling_message_type = this.handling_message_type; + this.handling_message_type = msg_type; var handler_name = 'on' + msg_type; if (typeof(this.state[handler_name]) !== "undefined") { this.state[handler_name](this, msg_type, message); } else { this.default_handler(msg_type, message); } + this.handling_message_type = old_handling_message_type; }; FSMController.prototype.default_handler = function(msg_type, message) { - if (this.next_controller !== null) { - this.next_controller.handle_message(msg_type, message); - } + this.delegate_channel.send(msg_type, message); }; function _State () { diff --git a/awx/network_ui/static/network_ui/src/group.js b/awx/network_ui/static/network_ui/src/group.js index c501a281f9..21e705f3b6 100644 --- a/awx/network_ui/static/network_ui/src/group.js +++ b/awx/network_ui/static/network_ui/src/group.js @@ -91,7 +91,7 @@ exports.Placing = Placing; _State.prototype.onUnselectAll = function (controller, msg_type, $event) { controller.changeState(Ready); - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; _Resize.prototype.onMouseUp = function (controller, msg_type, $event) { @@ -343,7 +343,7 @@ _Move.prototype.end = function (controller) { _Ready.prototype.onMouseMove = function (controller, msg_type, $event) { if (controller.scope.hide_groups) { - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); return; } @@ -353,14 +353,14 @@ _Ready.prototype.onMouseMove = function (controller, msg_type, $event) { controller.scope.groups[i].update_hightlighted(controller.scope.scaledX, controller.scope.scaledY); } - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; _Ready.prototype.onMouseDown = function (controller, msg_type, $event) { if (controller.scope.hide_groups) { - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); return; } @@ -402,7 +402,7 @@ _Ready.prototype.onMouseDown = function (controller, msg_type, $event) { } } - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; _Ready.prototype.onMouseDown.transitions = ['Selected1', 'CornerSelected']; @@ -564,7 +564,7 @@ _Selected2.prototype.onKeyDown = function (controller, msg_type, $event) { groups[i].name)); } } else { - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); } }; _Selected2.prototype.onKeyDown.transitions = ['Ready']; @@ -610,5 +610,5 @@ _Placing.prototype.onMouseDown = function (controller) { controller.changeState(Resize); }; -_Placing.prototype.onMouseDown.transitions = ['CornerSelected']; +_Placing.prototype.onMouseDown.transitions = ['Resize']; diff --git a/awx/network_ui/static/network_ui/src/hotkeys.fsm.js b/awx/network_ui/static/network_ui/src/hotkeys.fsm.js index 5af0851548..51b4c1440b 100644 --- a/awx/network_ui/static/network_ui/src/hotkeys.fsm.js +++ b/awx/network_ui/static/network_ui/src/hotkeys.fsm.js @@ -45,16 +45,16 @@ _Enabled.prototype.onKeyDown = function(controller, msg_type, $event) { var scope = controller.scope; if ($event.key === 'c' && ($event.ctrlKey || $event.metaKey)) { - scope.first_controller.handle_message("CopySelected", $event); + scope.first_channel.send("CopySelected", $event); } if ($event.key === 'l') { - scope.first_controller.handle_message("NewLink", $event); + scope.first_channel.send("NewLink", $event); return; } if ($event.key === 'm') { - scope.first_controller.handle_message("NewStream", $event); + scope.first_channel.send("NewStream", $event); } if ($event.key === 'd') { @@ -75,27 +75,27 @@ _Enabled.prototype.onKeyDown = function(controller, msg_type, $event) { } if ($event.key === 'r') { - scope.first_controller.handle_message("NewDevice", new messages.NewDevice("router")); + scope.first_channel.send("NewDevice", new messages.NewDevice("router")); return; } else if ($event.key === 's') { - scope.first_controller.handle_message("NewDevice", new messages.NewDevice("switch")); + scope.first_channel.send("NewDevice", new messages.NewDevice("switch")); return; } else if ($event.key === 'a') { - scope.first_controller.handle_message("NewGroup", new messages.NewGroup("rack")); + scope.first_channel.send("NewGroup", new messages.NewGroup("rack")); return; } else if ($event.key === 'h') { - scope.first_controller.handle_message("NewDevice", new messages.NewDevice("host")); + scope.first_channel.send("NewDevice", new messages.NewDevice("host")); return; } else if ($event.key === 'g') { - scope.first_controller.handle_message("NewGroup", new messages.NewGroup("group")); + scope.first_channel.send("NewGroup", new messages.NewGroup("group")); return; } else if ($event.key === 'e') { - scope.first_controller.handle_message("NewGroup", new messages.NewGroup("site")); + scope.first_channel.send("NewGroup", new messages.NewGroup("site")); return; } else if ($event.key === '0') { @@ -106,7 +106,7 @@ _Enabled.prototype.onKeyDown = function(controller, msg_type, $event) { scope.updatePanAndScale(); } - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; _Start.prototype.start = function (controller) { diff --git a/awx/network_ui/static/network_ui/src/link.js b/awx/network_ui/static/network_ui/src/link.js index 5ec1170080..05f17573f5 100644 --- a/awx/network_ui/static/network_ui/src/link.js +++ b/awx/network_ui/static/network_ui/src/link.js @@ -51,7 +51,7 @@ _Ready.prototype.onNewLink = function (controller, msg_type, message) { controller.scope.clear_selections(); controller.changeState(Selecting); - controller.next_controller.handle_message(msg_type, message); + controller.delegate_channel.send(msg_type, message); }; _Ready.prototype.onNewLink.transitions = ['Selecting']; diff --git a/awx/network_ui/static/network_ui/src/messages.js b/awx/network_ui/static/network_ui/src/messages.js index 3499b3cad5..ef80dd1511 100644 --- a/awx/network_ui/static/network_ui/src/messages.js +++ b/awx/network_ui/static/network_ui/src/messages.js @@ -422,3 +422,25 @@ function StreamUnSelected(sender, id) { this.id = id; } exports.StreamUnSelected = StreamUnSelected; + +function FSMTrace(order, fsm_name, from_state, to_state, recv_message_type) { + this.msg_type = 'FSMTrace'; + this.order = order; + this.sender = 0; + this.trace_id = 0; + this.fsm_name = fsm_name; + this.from_state = from_state; + this.to_state = to_state; + this.recv_message_type = recv_message_type; +} +exports.FSMTrace = FSMTrace; + +function ChannelTrace(from_fsm, to_fsm, sent_message_type) { + this.msg_type = 'ChannelTrace'; + this.sender = 0; + this.trace_id = 0; + this.from_fsm = from_fsm; + this.to_fsm = to_fsm; + this.sent_message_type = sent_message_type; +} +exports.ChannelTrace = ChannelTrace; diff --git a/awx/network_ui/static/network_ui/src/mode.fsm.js b/awx/network_ui/static/network_ui/src/mode.fsm.js index 4749892d8e..bf657dd82d 100644 --- a/awx/network_ui/static/network_ui/src/mode.fsm.js +++ b/awx/network_ui/static/network_ui/src/mode.fsm.js @@ -83,7 +83,7 @@ _Interface.prototype.onMouseWheel = function (controller, msg_type, $event) { //controller.changeState(Device); - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; _Interface.prototype.onMouseWheel.transitions = ['Device']; @@ -110,7 +110,7 @@ _Site.prototype.onMouseWheel = function (controller, msg_type, $event) { controller.changeState(Rack); } - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; _Site.prototype.onMouseWheel.transitions = ['MultiSite', 'Rack']; @@ -119,7 +119,7 @@ _Site.prototype.onMouseWheel.transitions = ['MultiSite', 'Rack']; _Process.prototype.onMouseWheel = function (controller, msg_type, $event) { - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); //controller.changeState(Device); @@ -145,7 +145,7 @@ _MultiSite.prototype.onMouseWheel = function (controller, msg_type, $event) { controller.changeState(Site); } - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; _MultiSite.prototype.onMouseWheel.transitions = ['Site']; @@ -171,7 +171,7 @@ _Device.prototype.onMouseWheel = function (controller, msg_type, $event) { controller.changeState(Rack); } - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; _Device.prototype.onMouseWheel.transitions = ['Process', 'Interface', 'Rack']; @@ -200,6 +200,6 @@ _Rack.prototype.onMouseWheel = function (controller, msg_type, $event) { controller.changeState(Device); } - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; _Rack.prototype.onMouseWheel.transitions = ['Site', 'Device']; diff --git a/awx/network_ui/static/network_ui/src/models.js b/awx/network_ui/static/network_ui/src/models.js index 47efc02fd0..f57b207339 100644 --- a/awx/network_ui/static/network_ui/src/models.js +++ b/awx/network_ui/static/network_ui/src/models.js @@ -289,7 +289,7 @@ Link.prototype.plength = function (x, y) { return util.pDistance(x, y, x1, y1, x2, y2); }; -function ActionIcon(name, x, y, r, callback, enabled) { +function ActionIcon(name, x, y, r, callback, enabled, tracer) { this.name = name; this.x = x; this.y = y; @@ -298,7 +298,7 @@ function ActionIcon(name, x, y, r, callback, enabled) { this.is_pressed = false; this.mouse_over = false; this.enabled = enabled; - this.fsm = new fsm.FSMController(this, enabled ? button.Start : button.Disabled, null, name+'button_fsm'); + this.fsm = new fsm.FSMController(this, "button_fsm", enabled ? button.Start : button.Disabled, tracer); } exports.ActionIcon = ActionIcon; @@ -311,7 +311,7 @@ ActionIcon.prototype.is_selected = function (x, y) { }; -function Button(name, x, y, width, height, callback) { +function Button(name, x, y, width, height, callback, tracer) { this.name = name; this.x = x; this.y = y; @@ -321,7 +321,7 @@ function Button(name, x, y, width, height, callback) { this.is_pressed = false; this.mouse_over = false; this.enabled = true; - this.fsm = new fsm.FSMController(this, button.Start, null, name+'button_fsm'); + this.fsm = new fsm.FSMController(this, "button_fsm", button.Start, tracer); } exports.Button = Button; @@ -336,7 +336,7 @@ Button.prototype.is_selected = function (x, y) { }; -function ToggleButton(name, x, y, width, height, toggle_callback, untoggle_callback, default_toggled) { +function ToggleButton(name, x, y, width, height, toggle_callback, untoggle_callback, default_toggled, tracer) { this.name = name; this.x = x; this.y = y; @@ -349,7 +349,7 @@ function ToggleButton(name, x, y, width, height, toggle_callback, untoggle_callb this.untoggle_callback = untoggle_callback; this.mouse_over = false; this.enabled = true; - this.fsm = new fsm.FSMController(this, button.Start, null, name+'toggle_button_fsm'); + this.fsm = new fsm.FSMController(this, "button_fsm", button.Start, tracer); } inherits(ToggleButton, Button); exports.ToggleButton = ToggleButton; @@ -365,7 +365,7 @@ ToggleButton.prototype.toggle = function () { } }; -function ContextMenu(name, x, y, width, height, callback, enabled, buttons) { +function ContextMenu(name, x, y, width, height, callback, enabled, buttons, tracer) { this.name = name; this.x = x; this.y = y; @@ -376,7 +376,7 @@ function ContextMenu(name, x, y, width, height, callback, enabled, buttons) { this.mouse_over = false; this.enabled = enabled; this.buttons = buttons; - this.fsm = new fsm.FSMController(this, button.Start, null, name+'button_fsm'); + this.fsm = new fsm.FSMController(this, "button_fsm", button.Start, tracer); } exports.ContextMenu = ContextMenu; @@ -390,7 +390,7 @@ ContextMenu.prototype.is_selected = function (x, y) { }; -function ContextMenuButton(name, x, y, width, height, callback) { +function ContextMenuButton(name, x, y, width, height, callback, tracer) { this.name = name; this.x = x; this.y = y; @@ -400,7 +400,7 @@ function ContextMenuButton(name, x, y, width, height, callback) { this.is_pressed = false; this.mouse_over = false; this.enabled = true; - this.fsm = new fsm.FSMController(this, button.Start, null, name+'button_fsm'); + this.fsm = new fsm.FSMController(this, "button_fsm", button.Start, tracer); } exports.ContextMenuButton = ContextMenuButton; diff --git a/awx/network_ui/static/network_ui/src/move.js b/awx/network_ui/static/network_ui/src/move.js index 3a9f9a0d12..3f1fbb70cf 100644 --- a/awx/network_ui/static/network_ui/src/move.js +++ b/awx/network_ui/static/network_ui/src/move.js @@ -79,7 +79,7 @@ exports.Placing = Placing; _State.prototype.onUnselectAll = function (controller, msg_type, $event) { controller.changeState(Ready); - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; _Ready.prototype.onNewDevice = function (controller, msg_type, message) { @@ -209,7 +209,7 @@ _Ready.prototype.onMouseDown = function (controller, msg_type, $event) { } else if (last_selected.last_selected_interface !== null) { controller.changeState(Selected1); } else { - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); } }; _Ready.prototype.onMouseDown.transitions = ['Selected1']; @@ -345,7 +345,7 @@ _Selected2.prototype.onKeyDown = function (controller, msg_type, $event) { } } - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; _Selected2.prototype.onKeyDown.transitions = ['Ready']; diff --git a/awx/network_ui/static/network_ui/src/network.ui.controller.js b/awx/network_ui/static/network_ui/src/network.ui.controller.js index d5ad0b59f3..06fafe8669 100644 --- a/awx/network_ui/static/network_ui/src/network.ui.controller.js +++ b/awx/network_ui/static/network_ui/src/network.ui.controller.js @@ -1,5 +1,4 @@ /* Copyright (c) 2017 Red Hat, Inc. */ -// var _ = require('lodash'); var angular = require('angular'); var fsm = require('./fsm.js'); var null_fsm = require('./null.fsm.js'); @@ -30,13 +29,14 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.http = $http; $scope.api_token = ''; - $scope.disconnected = true; + $scope.disconnected = false; $scope.topology_id = $location.search().topology_id || 0; // Create a web socket to connect to the backend server // $scope.inventory_id = $location.search().inventory_id || 1; + $scope.initial_messages = []; if (!$scope.disconnected) { $scope.control_socket = new ReconnectingWebSocket("wss://" + window.location.host + "/network_ui/topology?topology_id=" + $scope.topology_id, null, @@ -112,19 +112,43 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, 'y': 0, 'width': 0, 'height': 0}; + $scope.trace_id_seq = util.natural_numbers(0); + $scope.trace_order_seq = util.natural_numbers(0); + $scope.trace_id = $scope.trace_id_seq(); + + $scope.send_trace_message = function (message) { + console.log(message); + message.sender = $scope.client_id; + message.trace_id = $scope.trace_id; + message.message_id = $scope.message_id_seq(); + var data = messages.serialize(message); + if (!$scope.disconnected) { + try { + $scope.control_socket.send(data); + } + catch(err) { + $scope.initial_messages.push(message); + } + } else { + console.log(data); + } + }; + + //Define the FSMs + $scope.null_controller = new fsm.FSMController($scope, "null_fsm", null_fsm.Start, $scope); + $scope.hotkeys_controller = new fsm.FSMController($scope, "hotkeys_fsm", hotkeys.Start, $scope); + $scope.view_controller = new fsm.FSMController($scope, "view_fsm", view.Start, $scope); + $scope.device_detail_controller = new fsm.FSMController($scope, "device_detail_fsm", device_detail_fsm.Start, $scope); + $scope.move_controller = new fsm.FSMController($scope, "move_fsm", move.Start, $scope); + $scope.link_controller = new fsm.FSMController($scope, "link_fsm", link.Start, $scope); + $scope.stream_controller = new fsm.FSMController($scope, "stream_fsm", stream_fsm.Start, $scope); + $scope.group_controller = new fsm.FSMController($scope, "group_fsm", group.Start, $scope); + $scope.rack_controller = new fsm.FSMController($scope, "rack_fsm", rack_fsm.Disable, $scope); + $scope.site_controller = new fsm.FSMController($scope, "site_fsm", site_fsm.Disable, $scope); + $scope.buttons_controller = new fsm.FSMController($scope, "buttons_fsm", buttons.Start, $scope); + $scope.time_controller = new fsm.FSMController($scope, "time_fsm", time.Start, $scope); + $scope.app_toolbox_controller = new fsm.FSMController($scope, "toolbox_fsm", toolbox_fsm.Start, $scope); - $scope.null_controller = new fsm.FSMController($scope, null_fsm.Start, null, 'null_fsm'); - $scope.hotkeys_controller = new fsm.FSMController($scope, hotkeys.Start, $scope.null_controller, 'hotkeys_fsm'); - $scope.view_controller = new fsm.FSMController($scope, view.Start, $scope.hotkeys_controller, 'null_fsm'); - $scope.device_detail_controller = new fsm.FSMController($scope, device_detail_fsm.Start, $scope.view_controller, 'device_detail_fsm'); - $scope.move_controller = new fsm.FSMController($scope, move.Start, $scope.device_detail_controller, 'move_fsm'); - $scope.link_controller = new fsm.FSMController($scope, link.Start, $scope.move_controller, 'link_fsm'); - $scope.stream_controller = new fsm.FSMController($scope, stream_fsm.Start, $scope.link_controller, 'stream_fsm'); - $scope.group_controller = new fsm.FSMController($scope, group.Start, $scope.stream_controller, 'group_fsm'); - $scope.rack_controller = new fsm.FSMController($scope, rack_fsm.Disable, $scope.group_controller, 'rack_fsm'); - $scope.site_controller = new fsm.FSMController($scope, site_fsm.Disable, $scope.rack_controller, 'site_fsm'); - $scope.time_controller = new fsm.FSMController($scope, time.Start, $scope.site_controller, 'time_fsm'); - $scope.app_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Disabled, $scope.time_controller, 'toolbox_fsm'); //App Toolbox Setup $scope.app_toolbox = new models.ToolBox(0, 'Process', 'app', 0, 40, 200, $scope.graph.height - 40); $scope.app_toolbox.title_coordinates = {x: 70, y: 70}; @@ -133,7 +157,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.app_toolbox_controller.toolbox = $scope.app_toolbox; $scope.app_toolbox_controller.debug = true; $scope.app_toolbox_controller.dropped_action = function (selected_item) { - $scope.first_controller.handle_message("PasteProcess", new messages.PasteProcess(selected_item)); + $scope.first_channel.send("PasteProcess", new messages.PasteProcess(selected_item)); }; $scope.app_toolbox.items.push(new models.Process(0, 'BGP', 'process', 0, 0)); @@ -145,19 +169,19 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.app_toolbox.items[i].icon = true; } - $scope.inventory_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.app_toolbox_controller, 'inventory_toolbox_fsm'); + $scope.inventory_toolbox_controller = new fsm.FSMController($scope, "toolbox_fsm", toolbox_fsm.Start, $scope); + function add_host (host) { + console.log(host); + var device = new models.Device(0, host.data.name, 0, 0, host.data.type); + device.icon = true; + $scope.inventory_toolbox.items.push(device); + } //Inventory Toolbox Setup $scope.inventory_toolbox = new models.ToolBox(0, 'Inventory', 'device', 0, 40, 200, $scope.graph.height - 40); if (!$scope.disconnected) { console.log($location.protocol() + "://" + $location.host() + ':' + $location.port()); console.log($scope.my_location); - var add_host = function(host) { - console.log(host); - var device = new models.Device(0, host.data.name, 0, 0, host.data.type); - device.icon = true; - $scope.inventory_toolbox.items.push(device); - }; $http.get('/api/v2/inventories/' + $scope.inventory_id + '/hosts/?format=json') .then(function(inventory) { console.log(inventory); @@ -191,11 +215,11 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.inventory_toolbox_controller.remove_on_drop = true; $scope.inventory_toolbox_controller.debug = true; $scope.inventory_toolbox_controller.dropped_action = function (selected_item) { - $scope.first_controller.handle_message("PasteDevice", new messages.PasteDevice(selected_item)); + $scope.first_channel.send("PasteDevice", new messages.PasteDevice(selected_item)); }; //End Inventory Toolbox Setup - $scope.rack_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.inventory_toolbox_controller, 'rack_toolbox_fsm'); + $scope.rack_toolbox_controller = new fsm.FSMController($scope, "toolbox_fsm", toolbox_fsm.Start, $scope); //Rack Toolbox Setup $scope.rack_toolbox = new models.ToolBox(0, 'Rack', 'rack', 0, 40, 200, $scope.graph.height - 40); $scope.rack_toolbox.title_coordinates = {x: 80, y: 70}; @@ -205,14 +229,14 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.rack_toolbox_controller.toolbox = $scope.rack_toolbox; $scope.rack_toolbox_controller.debug = true; $scope.rack_toolbox_controller.dropped_action = function (selected_item) { - $scope.first_controller.handle_message("PasteRack", new messages.PasteRack(selected_item)); + $scope.first_channel.send("PasteRack", new messages.PasteRack(selected_item)); }; for(i = 0; i < $scope.rack_toolbox.items.length; i++) { $scope.rack_toolbox.items[i].icon = true; $scope.rack_toolbox.items[i].selected = false; } //End Rack Toolbox Setup - $scope.site_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.rack_toolbox_controller, 'site_toolbox_fsm'); + $scope.site_toolbox_controller = new fsm.FSMController($scope, "toolbox_fsm", toolbox_fsm.Start, $scope); //Site Toolbox Setup $scope.site_toolbox = new models.ToolBox(0, 'Sites', 'sites', 0, 40, 200, $scope.graph.height - 40); $scope.site_toolbox.title_coordinates = {x: 80, y: 70}; @@ -222,16 +246,67 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.site_toolbox_controller.toolbox = $scope.site_toolbox; $scope.site_toolbox_controller.debug = true; $scope.site_toolbox_controller.dropped_action = function (selected_item) { - $scope.first_controller.handle_message("PasteSite", new messages.PasteSite(selected_item)); + $scope.first_channel.send("PasteSite", new messages.PasteSite(selected_item)); }; for(i = 0; i < $scope.site_toolbox.items.length; i++) { $scope.site_toolbox.items[i].icon = true; $scope.site_toolbox.items[i].selected = false; } //End Site Toolbox Setup - $scope.buttons_controller = new fsm.FSMController($scope, buttons.Start, $scope.site_toolbox_controller, 'buttons_fsm'); - $scope.mode_controller = new fsm.FSMController($scope, mode_fsm.Start, $scope.buttons_controller, 'mode_fsm'); - $scope.first_controller = $scope.mode_controller; + + $scope.mode_controller = new fsm.FSMController($scope, "mode_fsm", mode_fsm.Start, $scope); + + //Wire up the FSMs + $scope.view_controller.delegate_channel = new fsm.Channel($scope.view_controller, + $scope.hotkeys_controller, + $scope); + $scope.device_detail_controller.delegate_channel = new fsm.Channel($scope.device_detail_controller, + $scope.view_controller, + $scope); + $scope.move_controller.delegate_channel = new fsm.Channel($scope.move_controller, + $scope.device_detail_controller, + $scope); + $scope.link_controller.delegate_channel = new fsm.Channel($scope.link_controller, + $scope.move_controller, + $scope); + $scope.stream_controller.delegate_channel = new fsm.Channel($scope.stream_controller, + $scope.link_controller, + $scope); + $scope.group_controller.delegate_channel = new fsm.Channel($scope.group_controller, + $scope.stream_controller, + $scope); + $scope.rack_controller.delegate_channel = new fsm.Channel($scope.rack_controller, + $scope.group_controller, + $scope); + $scope.site_controller.delegate_channel = new fsm.Channel($scope.site_controller, + $scope.rack_controller, + $scope); + $scope.app_toolbox_controller.delegate_channel = new fsm.Channel($scope.app_toolbox_controller, + $scope.site_controller, + $scope); + $scope.inventory_toolbox_controller.delegate_channel = new fsm.Channel($scope.inventory_toolbox_controller, + $scope.app_toolbox_controller, + $scope); + $scope.rack_toolbox_controller.delegate_channel = new fsm.Channel($scope.rack_toolbox_controller, + $scope.inventory_toolbox_controller, + $scope); + $scope.site_toolbox_controller.delegate_channel = new fsm.Channel($scope.site_toolbox_controller, + $scope.rack_toolbox_controller, + $scope); + $scope.buttons_controller.delegate_channel = new fsm.Channel($scope.buttons_controller, + $scope.site_toolbox_controller, + $scope); + $scope.time_controller.delegate_channel = new fsm.Channel($scope.time_controller, + $scope.buttons_controller, + $scope); + $scope.mode_controller.delegate_channel = new fsm.Channel($scope.mode_controller, + $scope.time_controller, + $scope); + + $scope.first_channel = new fsm.Channel(null, + $scope.mode_controller, + $scope); + var getMouseEventResult = function (mouseEvent) { return "(" + mouseEvent.x + ", " + mouseEvent.y + ")"; }; @@ -406,7 +481,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.x, $event.y, $event.type)); } $scope.last_event = $event; - $scope.first_controller.handle_message('MouseDown', $event); + $scope.first_channel.send('MouseDown', $event); $scope.onMouseDownResult = getMouseEventResult($event); $event.preventDefault(); }; @@ -417,7 +492,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.x, $event.y, $event.type)); } $scope.last_event = $event; - $scope.first_controller.handle_message('MouseUp', $event); + $scope.first_channel.send('MouseUp', $event); $scope.onMouseUpResult = getMouseEventResult($event); $event.preventDefault(); }; @@ -444,7 +519,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.mouseX = $event.x; $scope.mouseY = $event.y; $scope.updateScaledXY(); - $scope.first_controller.handle_message('MouseMove', $event); + $scope.first_channel.send('MouseMove', $event); $scope.onMouseMoveResult = getMouseEventResult($event); $event.preventDefault(); }; @@ -471,7 +546,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.send_control_message(new messages.MouseWheelEvent($scope.client_id, delta, deltaX, deltaY, $event.type, $event.originalEvent.metaKey)); } $scope.last_event = $event; - $scope.first_controller.handle_message('MouseWheel', [$event, delta, deltaX, deltaY]); + $scope.first_channel.send('MouseWheel', [$event, delta, deltaX, deltaY]); event.preventDefault(); }; @@ -489,7 +564,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.last_event = $event; $scope.last_key = $event.key; $scope.last_key_code = $event.keyCode; - $scope.first_controller.handle_message('KeyDown', $event); + $scope.first_channel.send('KeyDown', $event); $scope.$apply(); $event.preventDefault(); }; @@ -518,7 +593,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.mouseY = $event.touches[0].screenY; $scope.updateScaledXY(); } - $scope.first_controller.handle_message('TouchStart', $event); + $scope.first_channel.send('TouchStart', $event); $scope.onTouchStartEvent = $event; $event.preventDefault(); }; @@ -533,7 +608,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, if ($scope.recording) { $scope.send_control_message(new messages.TouchEvent($scope.client_id, "touchend", touches)); } - $scope.first_controller.handle_message('TouchEnd', $event); + $scope.first_channel.send('TouchEnd', $event); $scope.onTouchEndEvent = $event; $event.preventDefault(); }; @@ -558,7 +633,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.updateScaledXY(); } - $scope.first_controller.handle_message('TouchMove', $event); + $scope.first_channel.send('TouchMove', $event); $scope.onTouchMoveEvent = $event; $event.preventDefault(); }; @@ -586,7 +661,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, // $scope.onToggleToolboxButtonLeft = function (button) { console.log(button.name); - $scope.first_controller.handle_message("ToggleToolbox", {}); + $scope.first_channel.send("ToggleToolbox", {}); $scope.action_icons[0].fsm.handle_message("Disable", {}); $scope.action_icons[1].fsm.handle_message("Enable", {}); $scope.overall_toolbox_collapsed = !$scope.overall_toolbox_collapsed; @@ -594,7 +669,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.onToggleToolboxButtonRight = function (button) { console.log(button.name); - $scope.first_controller.handle_message("ToggleToolbox", {}); + $scope.first_channel.send("ToggleToolbox", {}); $scope.action_icons[0].fsm.handle_message("Enable", {}); $scope.action_icons[1].fsm.handle_message("Disable", {}); $scope.overall_toolbox_collapsed = !$scope.overall_toolbox_collapsed; @@ -696,54 +771,61 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, // Context Menu Buttons $scope.context_menu_buttons = [ - new models.ContextMenuButton("Edit", 210, 200, 160, 26, $scope.onDetailsContextButton), - new models.ContextMenuButton("Details", 236, 231, 160, 26, $scope.onDetailsContextButton) + new models.ContextMenuButton("Edit", 210, 200, 160, 26, $scope.onDetailsContextButton, $scope), + new models.ContextMenuButton("Details", 236, 231, 160, 26, $scope.onDetailsContextButton, $scope) ]; // Context Menus $scope.context_menus = [ - new models.ContextMenu('HOST', 210, 200, 160, 64, $scope.contextMenuCallback, true, $scope.context_menu_buttons) + new models.ContextMenu('HOST', 210, 200, 160, 64, $scope.contextMenuCallback, true, $scope.context_menu_buttons, $scope) ]; // Icons $scope.action_icons = [ - new models.ActionIcon("chevron-left", 170, $scope.graph.height/2, 16, $scope.onToggleToolboxButtonLeft, true), - new models.ActionIcon("chevron-right", 15, $scope.graph.height/2, 16, $scope.onToggleToolboxButtonRight, false) + new models.ActionIcon("chevron-left", 170, $scope.graph.height/2, 16, $scope.onToggleToolboxButtonLeft, true, $scope), + new models.ActionIcon("chevron-right", 15, $scope.graph.height/2, 16, $scope.onToggleToolboxButtonRight, false, $scope) ]; + $scope.onDownloadTraceButton = function (button) { + console.log(button.label); + window.open("/network_ui/download_trace?topology_id=" + $scope.topology_id + "&trace_id=" + $scope.trace_id + "&client_id=" + $scope.client_id); + }; // Buttons var button_offset = 200; $scope.buttons = [ - new models.Button("DEPLOY", button_offset + 10, 48, 70, 30, $scope.onDeployButton), - new models.Button("DESTROY", button_offset + 90, 48, 80, 30, $scope.onDestroyButton), - new models.Button("RECORD", button_offset + 180, 48, 80, 30, $scope.onRecordButton), - new models.Button("EXPORT", button_offset + 270, 48, 70, 30, $scope.onExportButton), - new models.Button("DISCOVER", button_offset + 350, 48, 80, 30, $scope.onDiscoverButton), - new models.Button("LAYOUT", button_offset + 440, 48, 70, 30, $scope.onLayoutButton), - new models.Button("CONFIGURE", button_offset + 520, 48, 90, 30, $scope.onConfigureButton), - new models.Button("EXPORT YAML", button_offset + 620, 48, 120, 30, $scope.onExportYamlButton), + new models.Button("DEPLOY", button_offset + 10, 48, 70, 30, $scope.onDeployButton, $scope), + new models.Button("DESTROY", button_offset + 90, 48, 80, 30, $scope.onDestroyButton, $scope), + new models.Button("RECORD", button_offset + 180, 48, 80, 30, $scope.onRecordButton, $scope), + new models.Button("EXPORT", button_offset + 270, 48, 70, 30, $scope.onExportButton, $scope), + new models.Button("DISCOVER", button_offset + 350, 48, 80, 30, $scope.onDiscoverButton, $scope), + new models.Button("LAYOUT", button_offset + 440, 48, 70, 30, $scope.onLayoutButton, $scope), + new models.Button("CONFIGURE", button_offset + 520, 48, 90, 30, $scope.onConfigureButton, $scope), + new models.Button("EXPORT YAML", button_offset + 620, 48, 120, 30, $scope.onExportYamlButton, $scope), + new models.Button("DOWNLOAD TRACE", button_offset + 750, 48, 150, 30, $scope.onDownloadTraceButton, $scope), ]; var LAYERS_X = 160; $scope.layers = [ - new models.ToggleButton("APPLICATION", $scope.graph.width - LAYERS_X, 10, 120, 30, util.noop, util.noop, true), - new models.ToggleButton("PRESENTATION", $scope.graph.width - LAYERS_X, 50, 120, 30, util.noop, util.noop, true), - new models.ToggleButton("SESSION", $scope.graph.width - LAYERS_X, 90, 120, 30, util.noop, util.noop, true), - new models.ToggleButton("TRANSPORT", $scope.graph.width - LAYERS_X, 130, 120, 30, util.noop, util.noop, true), - new models.ToggleButton("NETWORK", $scope.graph.width - LAYERS_X, 170, 120, 30, util.noop, util.noop, true), - new models.ToggleButton("DATA-LINK", $scope.graph.width - LAYERS_X, 210, 120, 30, util.noop, util.noop, true), + new models.ToggleButton("APPLICATION", $scope.graph.width - LAYERS_X, 10, 120, 30, util.noop, util.noop, true, $scope), + new models.ToggleButton("PRESENTATION", $scope.graph.width - LAYERS_X, 50, 120, 30, util.noop, util.noop, true, $scope), + new models.ToggleButton("SESSION", $scope.graph.width - LAYERS_X, 90, 120, 30, util.noop, util.noop, true, $scope), + new models.ToggleButton("TRANSPORT", $scope.graph.width - LAYERS_X, 130, 120, 30, util.noop, util.noop, true, $scope), + new models.ToggleButton("NETWORK", $scope.graph.width - LAYERS_X, 170, 120, 30, util.noop, util.noop, true, $scope), + new models.ToggleButton("DATA-LINK", $scope.graph.width - LAYERS_X, 210, 120, 30, util.noop, util.noop, true, $scope), new models.ToggleButton("PHYSICAL", $scope.graph.width - LAYERS_X, 250, 120, 30, $scope.onTogglePhysical, $scope.onUnTogglePhysical, - true), + true, + $scope), new models.ToggleButton("GROUP", $scope.graph.width - LAYERS_X, 290, 120, 30, $scope.onToggleGroup, $scope.onUnToggleGroup, - true) + true, + $scope) ]; $scope.layers = []; @@ -1213,6 +1295,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.onClientId = function(data) { $scope.client_id = data; + $scope.send_initial_messages(); }; $scope.onTopology = function(data) { @@ -1559,12 +1642,26 @@ var NetworkUIController = function($scope, $document, $location, $window, $http, $scope.control_socket.onmessage = function(message) { - $scope.first_controller.handle_message('Message', message); + $scope.first_channel.send('Message', message); $scope.$apply(); }; $scope.control_socket.onopen = function() { - //Ignore + //ignore + }; + + $scope.send_initial_messages = function() { + var i = 0; + var messages_to_send = $scope.initial_messages; + var message = null; + var data = null; + $scope.initial_messages = []; + for(i = 0; i < messages_to_send.length; i++) { + message = messages_to_send[i]; + message.sender = $scope.client_id; + data = messages.serialize(message); + $scope.control_socket.send(data); + } }; // Call onopen directly if $scope.control_socket is already open diff --git a/awx/network_ui/static/network_ui/src/network.widgets.controller.js b/awx/network_ui/static/network_ui/src/network.widgets.controller.js index 7fa35f2453..10529371e7 100644 --- a/awx/network_ui/static/network_ui/src/network.widgets.controller.js +++ b/awx/network_ui/static/network_ui/src/network.widgets.controller.js @@ -32,7 +32,8 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { $scope.topology_id = 0; $scope.control_socket = { - on_message: util.noop + on_message: util.noop, + send: util.noop }; $scope.history = []; $scope.client_id = 1; @@ -98,27 +99,45 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { 'y': 0, 'width': 0, 'height': 0}; + $scope.trace_id_seq = util.natural_numbers(0); + $scope.trace_order_seq = util.natural_numbers(0); + $scope.trace_id = $scope.trace_id_seq(); + + $scope.send_trace_message = function (message) { + console.log(message); + message.sender = $scope.client_id; + message.trace_id = $scope.trace_id; + message.message_id = $scope.message_id_seq(); + var data = messages.serialize(message); + if (!$scope.disconnected) { + $scope.control_socket.send(data); + } else { + console.log(data); + } + }; + + //Define the FSMs + $scope.null_controller = new fsm.FSMController($scope, "null_fsm", null_fsm.Start, $scope); + $scope.hotkeys_controller = new fsm.FSMController($scope, "hotkeys_fsm", hotkeys.Start, $scope); + $scope.view_controller = new fsm.FSMController($scope, "view_fsm", view.Start, $scope); + $scope.device_detail_controller = new fsm.FSMController($scope, "device_detail_fsm", device_detail_fsm.Start, $scope); + $scope.move_controller = new fsm.FSMController($scope, "move_fsm", move.Start, $scope); + $scope.link_controller = new fsm.FSMController($scope, "link_fsm", link.Start, $scope); + $scope.stream_controller = new fsm.FSMController($scope, "stream_fsm", stream_fsm.Start, $scope); + $scope.group_controller = new fsm.FSMController($scope, "group_fsm", group.Start, $scope); + $scope.rack_controller = new fsm.FSMController($scope, "rack_fsm", rack_fsm.Disable, $scope); + $scope.site_controller = new fsm.FSMController($scope, "site_fsm", site_fsm.Disable, $scope); + $scope.buttons_controller = new fsm.FSMController($scope, "buttons_fsm", buttons.Start, $scope); + $scope.time_controller = new fsm.FSMController($scope, "time_fsm", time.Start, $scope); + $scope.app_toolbox_controller = new fsm.FSMController($scope, "toolbox_fsm", toolbox_fsm.Start, $scope); - $scope.null_controller = new fsm.FSMController($scope, null_fsm.Start, null); - $scope.hotkeys_controller = new fsm.FSMController($scope, hotkeys.Start, $scope.null_controller); - $scope.view_controller = new fsm.FSMController($scope, view.Start, $scope.hotkeys_controller); - $scope.device_detail_controller = new fsm.FSMController($scope, device_detail_fsm.Start, $scope.view_controller); - $scope.move_controller = new fsm.FSMController($scope, move.Start, $scope.device_detail_controller); - $scope.link_controller = new fsm.FSMController($scope, link.Start, $scope.move_controller); - $scope.stream_controller = new fsm.FSMController($scope, stream_fsm.Start, $scope.link_controller); - $scope.group_controller = new fsm.FSMController($scope, group.Start, $scope.stream_controller); - $scope.rack_controller = new fsm.FSMController($scope, rack_fsm.Disable, $scope.group_controller); - $scope.site_controller = new fsm.FSMController($scope, site_fsm.Disable, $scope.rack_controller); - $scope.buttons_controller = new fsm.FSMController($scope, buttons.Start, $scope.site_controller); - $scope.time_controller = new fsm.FSMController($scope, time.Start, $scope.buttons_controller); - $scope.app_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.time_controller); //App Toolbox Setup $scope.app_toolbox = new models.ToolBox(0, 'Process', 'app', 10, 200, 150, $scope.graph.height - 200 - 100); $scope.app_toolbox.spacing = 150; $scope.app_toolbox.enabled = false; $scope.app_toolbox_controller.toolbox = $scope.app_toolbox; $scope.app_toolbox_controller.dropped_action = function (selected_item) { - $scope.first_controller.handle_message("PasteProcess", new messages.PasteProcess(selected_item)); + $scope.first_channel.send("PasteProcess", new messages.PasteProcess(selected_item)); }; $scope.app_toolbox.items.push(new models.Process(0, 'BGP', 'process', 0, 0)); $scope.app_toolbox.items.push(new models.Process(0, 'OSPF', 'process', 0, 0)); @@ -129,7 +148,7 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { $scope.app_toolbox.items[i].icon = true; } - $scope.inventory_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.app_toolbox_controller); + $scope.inventory_toolbox_controller = new fsm.FSMController($scope, "toolbox_fsm", toolbox_fsm.Start, $scope); //Inventory Toolbox Setup $scope.inventory_toolbox = new models.ToolBox(0, 'Inventory', 'device', 10, 200, 150, $scope.graph.height - 200 - 100); @@ -151,14 +170,14 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { $scope.inventory_toolbox_controller.toolbox = $scope.inventory_toolbox; $scope.inventory_toolbox_controller.remove_on_drop = true; $scope.inventory_toolbox_controller.dropped_action = function (selected_item) { - $scope.first_controller.handle_message("PasteDevice", new messages.PasteDevice(selected_item)); + $scope.first_channel.send("PasteDevice", new messages.PasteDevice(selected_item)); }; for(i = 0; i < $scope.inventory_toolbox.items.length; i++) { $scope.inventory_toolbox.items[i].icon = true; } //End Inventory Toolbox Setup - $scope.rack_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.inventory_toolbox_controller); + $scope.rack_toolbox_controller = new fsm.FSMController($scope, "toolbox_fsm", toolbox_fsm.Start, $scope); //Rack Toolbox Setup $scope.rack_toolbox = new models.ToolBox(0, 'Rack', 'rack', 10, 200, 150, $scope.graph.height - 200 - 100); $scope.rack_toolbox.items.push(new models.Group(0, 'Rack3', 'rack', 0, 0, 200, 1000, 'false')); @@ -167,14 +186,14 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { $scope.rack_toolbox_controller.remove_on_drop = false; $scope.rack_toolbox_controller.toolbox = $scope.rack_toolbox; $scope.rack_toolbox_controller.dropped_action = function (selected_item) { - $scope.first_controller.handle_message("PasteRack", new messages.PasteRack(selected_item)); + $scope.first_channel.send("PasteRack", new messages.PasteRack(selected_item)); }; for(i = 0; i < $scope.rack_toolbox.items.length; i++) { $scope.rack_toolbox.items[i].icon = true; $scope.rack_toolbox.items[i].selected = false; } //End Rack Toolbox Setup - $scope.site_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.rack_toolbox_controller); + $scope.site_toolbox_controller = new fsm.FSMController($scope, "toolbox_fsm", toolbox_fsm.Start, $scope); //Site Toolbox Setup $scope.site_toolbox = new models.ToolBox(0, 'Sites', 'sites', 10, 200, 150, $scope.graph.height - 200 - 100); $scope.site_toolbox.items.push(new models.Group(0, 'Site3', 'site', 0, 0, 1000, 1000, 'false')); @@ -183,7 +202,7 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { $scope.site_toolbox_controller.remove_on_drop = false; $scope.site_toolbox_controller.toolbox = $scope.site_toolbox; $scope.site_toolbox_controller.dropped_action = function (selected_item) { - $scope.first_controller.handle_message("PasteSite", new messages.PasteSite(selected_item)); + $scope.first_channel.send("PasteSite", new messages.PasteSite(selected_item)); }; for(i = 0; i < $scope.site_toolbox.items.length; i++) { $scope.site_toolbox.items[i].icon = true; @@ -191,8 +210,58 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { } //End Site Toolbox Setup - $scope.mode_controller = new fsm.FSMController($scope, mode_fsm.Start, $scope.site_toolbox_controller); - $scope.first_controller = $scope.mode_controller; + $scope.mode_controller = new fsm.FSMController($scope, "mode_fsm", mode_fsm.Start, $scope); + + //Wire up the FSMs + $scope.view_controller.delegate_channel = new fsm.Channel($scope.view_controller, + $scope.hotkeys_controller, + $scope); + $scope.device_detail_controller.delegate_channel = new fsm.Channel($scope.device_detail_controller, + $scope.view_controller, + $scope); + $scope.move_controller.delegate_channel = new fsm.Channel($scope.move_controller, + $scope.device_detail_controller, + $scope); + $scope.link_controller.delegate_channel = new fsm.Channel($scope.link_controller, + $scope.move_controller, + $scope); + $scope.stream_controller.delegate_channel = new fsm.Channel($scope.stream_controller, + $scope.link_controller, + $scope); + $scope.group_controller.delegate_channel = new fsm.Channel($scope.group_controller, + $scope.stream_controller, + $scope); + $scope.rack_controller.delegate_channel = new fsm.Channel($scope.rack_controller, + $scope.group_controller, + $scope); + $scope.site_controller.delegate_channel = new fsm.Channel($scope.site_controller, + $scope.rack_controller, + $scope); + $scope.buttons_controller.delegate_channel = new fsm.Channel($scope.buttons_controller, + $scope.site_controller, + $scope); + $scope.time_controller.delegate_channel = new fsm.Channel($scope.time_controller, + $scope.buttons_controller, + $scope); + $scope.app_toolbox_controller.delegate_channel = new fsm.Channel($scope.app_toolbox_controller, + $scope.time_controller, + $scope); + $scope.inventory_toolbox_controller.delegate_channel = new fsm.Channel($scope.inventory_toolbox_controller, + $scope.app_toolbox_controller, + $scope); + $scope.rack_toolbox_controller.delegate_channel = new fsm.Channel($scope.rack_toolbox_controller, + $scope.inventory_toolbox_controller, + $scope); + $scope.site_toolbox_controller.delegate_channel = new fsm.Channel($scope.site_toolbox_controller, + $scope.rack_toolbox_controller, + $scope); + $scope.mode_controller.delegate_channel = new fsm.Channel($scope.mode_controller, + $scope.site_toolbox_controller, + $scope); + + $scope.first_channel = new fsm.Channel(null, + $scope.mode_controller, + $scope); var dids = $scope.device_id_seq; var mids = $scope.message_id_seq; @@ -401,7 +470,7 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { $scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.offsetX, $event.offsetY, $event.type)); } $scope.last_event = $event; - $scope.first_controller.handle_message('MouseDown', $event); + $scope.first_channel.send('MouseDown', $event); $scope.onMouseDownResult = getMouseEventResult($event); $event.preventDefault(); }; @@ -411,7 +480,7 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { $scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.offsetX, $event.offsetY, $event.type)); } $scope.last_event = $event; - $scope.first_controller.handle_message('MouseUp', $event); + $scope.first_channel.send('MouseUp', $event); $scope.onMouseUpResult = getMouseEventResult($event); $event.preventDefault(); }; @@ -436,7 +505,7 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { $scope.mouseX = $event.offsetX; $scope.mouseY = $event.offsetY; $scope.updateScaledXY(); - $scope.first_controller.handle_message('MouseMove', $event); + $scope.first_channel.send('MouseMove', $event); $scope.onMouseMoveResult = getMouseEventResult($event); $event.preventDefault(); }; @@ -457,7 +526,7 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { $scope.send_control_message(new messages.MouseWheelEvent($scope.client_id, delta, deltaX, deltaY, $event.type, $event.originalEvent.metaKey)); } $scope.last_event = $event; - $scope.first_controller.handle_message('MouseWheel', [$event, delta, deltaX, deltaY]); + $scope.first_channel.send('MouseWheel', [$event, delta, deltaX, deltaY]); event.preventDefault(); }; @@ -475,7 +544,7 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { $scope.last_event = $event; $scope.last_key = $event.key; $scope.last_key_code = $event.keyCode; - $scope.first_controller.handle_message('KeyDown', $event); + $scope.first_channel.send('KeyDown', $event); $scope.$apply(); $event.preventDefault(); }; @@ -504,7 +573,7 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { $scope.mouseY = $event.touches[0].screenY; $scope.updateScaledXY(); } - $scope.first_controller.handle_message('TouchStart', $event); + $scope.first_channel.send('TouchStart', $event); $scope.onTouchStartEvent = $event; $event.preventDefault(); }; @@ -519,7 +588,7 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { if ($scope.recording) { $scope.send_control_message(new messages.TouchEvent($scope.client_id, "touchend", touches)); } - $scope.first_controller.handle_message('TouchEnd', $event); + $scope.first_channel.send('TouchEnd', $event); $scope.onTouchEndEvent = $event; $event.preventDefault(); }; @@ -544,7 +613,7 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { $scope.updateScaledXY(); } - $scope.first_controller.handle_message('TouchMove', $event); + $scope.first_channel.send('TouchMove', $event); $scope.onTouchMoveEvent = $event; $event.preventDefault(); }; @@ -636,15 +705,15 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { // Buttons $scope.buttons = [ - new models.Button("BUTTON1", 10, 10, 90, 30, util.noop), - new models.Button("BUTTON1", 110, 10, 90, 30, util.noop), + new models.Button("BUTTON1", 10, 10, 90, 30, util.noop, $scope), + new models.Button("BUTTON1", 110, 10, 90, 30, util.noop, $scope), ]; var LAYERS_X = 160; $scope.layers = [ - new models.ToggleButton("TOGGLEBUTTON1", $scope.graph.width - LAYERS_X, 10, 150, 30, util.noop, util.noop, true), - new models.ToggleButton("TOGGLEBUTTON2", $scope.graph.width - LAYERS_X, 50, 150, 30, util.noop, util.noop, true), + new models.ToggleButton("TOGGLEBUTTON1", $scope.graph.width - LAYERS_X, 10, 150, 30, util.noop, util.noop, true, $scope), + new models.ToggleButton("TOGGLEBUTTON2", $scope.graph.width - LAYERS_X, 50, 150, 30, util.noop, util.noop, true, $scope), ]; var STENCIL_X = 10; @@ -652,8 +721,8 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { var STENCIL_SPACING = 40; $scope.stencils = [ - new models.Button("BUTTON3", STENCIL_X, STENCIL_Y + STENCIL_SPACING * 0, 90, 30, util.noop), - new models.Button("BUTTON4", STENCIL_X, STENCIL_Y + STENCIL_SPACING * 1, 90, 30, util.noop), + new models.Button("BUTTON3", STENCIL_X, STENCIL_Y + STENCIL_SPACING * 0, 90, 30, util.noop, $scope), + new models.Button("BUTTON4", STENCIL_X, STENCIL_Y + STENCIL_SPACING * 1, 90, 30, util.noop, $scope), ]; $scope.all_buttons = []; @@ -1326,7 +1395,7 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { $scope.control_socket.onmessage = function(message) { - $scope.first_controller.handle_message('Message', message); + $scope.first_channel.send('Message', message); $scope.$apply(); }; @@ -1391,7 +1460,7 @@ var NetworkWidgetsController = function($scope, $document, $location, $window) { for (i =0; i < $scope.initial_messages.length; i++) { console.log(['Inital message', $scope.initial_messages[i]]); - $scope.first_controller.handle_message($scope.initial_messages[i][0], $scope.initial_messages[i][1]); + $scope.first_channel.send($scope.initial_messages[i][0], $scope.initial_messages[i][1]); } $scope.updateScaledXY(); diff --git a/awx/network_ui/static/network_ui/src/rack.fsm.js b/awx/network_ui/static/network_ui/src/rack.fsm.js index 27dc705550..af6216329a 100644 --- a/awx/network_ui/static/network_ui/src/rack.fsm.js +++ b/awx/network_ui/static/network_ui/src/rack.fsm.js @@ -284,7 +284,7 @@ _Selected2.prototype.onCopySelected = function (controller) { _Selected2.prototype.onKeyDown = function (controller, msg_type, $event) { //controller.changeState(Ready); - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; _Selected2.prototype.onKeyDown.transitions = ['Ready']; @@ -407,7 +407,7 @@ _Ready.prototype.onMouseDown = function (controller, msg_type, $event) { if (selected) { controller.changeState(Selected1); } else { - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); } }; _Ready.prototype.onMouseDown.transitions = ['Selected1']; diff --git a/awx/network_ui/static/network_ui/src/site.fsm.js b/awx/network_ui/static/network_ui/src/site.fsm.js index efeec22245..b8a120c5ee 100644 --- a/awx/network_ui/static/network_ui/src/site.fsm.js +++ b/awx/network_ui/static/network_ui/src/site.fsm.js @@ -367,7 +367,7 @@ _Selected2.prototype.onCopySelected = function (controller) { _Selected2.prototype.onKeyDown = function (controller, msg_type, $event) { //controller.changeState(Ready); - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); }; _Selected2.prototype.onKeyDown.transitions = ['Ready']; @@ -490,7 +490,7 @@ _Ready.prototype.onMouseDown = function (controller, msg_type, $event) { if (selected) { controller.changeState(Selected1); } else { - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); } }; _Ready.prototype.onMouseDown.transitions = ['Selected1']; diff --git a/awx/network_ui/static/network_ui/src/time.js b/awx/network_ui/static/network_ui/src/time.js index 4c985d74e3..349a606791 100644 --- a/awx/network_ui/static/network_ui/src/time.js +++ b/awx/network_ui/static/network_ui/src/time.js @@ -195,7 +195,7 @@ _Past.prototype.onMouseWheel = function (controller, msg_type, message) { this.redo(controller); } } else { - controller.next_controller.handle_message(msg_type, message); + controller.delegate_channel.send(msg_type, message); } }; @@ -218,7 +218,7 @@ _Past.prototype.onKeyDown = function(controller, msg_type, $event) { this.redo(controller); return; } else { - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); } }; _Past.prototype.onKeyDown.transitions = ['Present']; @@ -504,7 +504,7 @@ _Present.prototype.onMouseWheel = function (controller, msg_type, message) { this.undo(controller); } } else { - controller.next_controller.handle_message(msg_type, message); + controller.delegate_channel.send(msg_type, message); } }; @@ -521,7 +521,7 @@ _Present.prototype.onKeyDown = function(controller, msg_type, $event) { this.undo(controller); return; } else { - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); } }; _Present.prototype.onKeyDown.transitions = ['Past']; diff --git a/awx/network_ui/static/network_ui/src/toolbox.fsm.js b/awx/network_ui/static/network_ui/src/toolbox.fsm.js index 2fc2bed471..a4a226fc1f 100644 --- a/awx/network_ui/static/network_ui/src/toolbox.fsm.js +++ b/awx/network_ui/static/network_ui/src/toolbox.fsm.js @@ -145,7 +145,7 @@ _Selecting.prototype.onMouseDown = function (controller) { toolbox.selected_item.x = toolbox.x + toolbox.width/2; toolbox.selected_item.y = selected_item * toolbox.spacing + toolbox.y + toolbox.scroll_offset + toolbox.spacing/2; controller.scope.clear_selections(); - controller.scope.first_controller.handle_message("UnselectAll", {}); + controller.scope.first_channel.send("UnselectAll", {}); controller.changeState(Selected); } else { toolbox.selected_item = null; @@ -171,7 +171,7 @@ _Ready.prototype.onMouseDown = function (controller, msg_type, $event) { controller.handle_message(msg_type, $event); } else { - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); } }; _Ready.prototype.onMouseDown.transitions = ['Selecting']; @@ -188,7 +188,7 @@ _Ready.prototype.onMouseWheel = function (controller, msg_type, $event) { controller.handle_message(msg_type, $event); } else { - controller.next_controller.handle_message(msg_type, $event); + controller.delegate_channel.send(msg_type, $event); } }; _Ready.prototype.onMouseWheel.transitions = ['Scrolling']; @@ -196,7 +196,7 @@ _Ready.prototype.onMouseWheel.transitions = ['Scrolling']; _Ready.prototype.onToggleToolbox = function (controller, msg_type, message) { controller.changeState(OffScreen); - controller.next_controller.handle_message(msg_type, message); + controller.delegate_channel.send(msg_type, message); }; _Ready.prototype.onToggleToolbox.transitions = ['OffScreen']; @@ -256,7 +256,7 @@ _Move.prototype.onMouseMove = function (controller) { _OffScreen.prototype.onToggleToolbox = function (controller, msg_type, message) { controller.changeState(Ready); - controller.next_controller.handle_message(msg_type, message); + controller.delegate_channel.send(msg_type, message); }; _OffScreen.prototype.onToggleToolbox.transitions = ['Ready']; @@ -298,7 +298,7 @@ _OffScreen2.prototype.start = function (controller) { _OffScreen2.prototype.onToggleToolbox = function (controller, msg_type, message) { controller.changeState(Disabled); - controller.next_controller.handle_message(msg_type, message); + controller.delegate_channel.send(msg_type, message); }; _OffScreen2.prototype.onToggleToolbox.transitions = ['Disabled']; @@ -327,6 +327,6 @@ _Disabled.prototype.end = function (controller) { _Disabled.prototype.onToggleToolbox = function (controller, msg_type, message) { controller.changeState(OffScreen2); - controller.next_controller.handle_message(msg_type, message); + controller.delegate_channel.send(msg_type, message); }; _Disabled.prototype.onToggleToolbox.transitions = ['OffScreen2']; diff --git a/awx/network_ui/urls.py b/awx/network_ui/urls.py index 2d3c7b9906..5f4f885cdf 100644 --- a/awx/network_ui/urls.py +++ b/awx/network_ui/urls.py @@ -7,6 +7,7 @@ import awx.network_ui.routing app_name = 'network_ui' urlpatterns = [ + url(r'^download_trace$', views.download_trace, name='download_trace'), url(r'^topology.json$', views.json_topology_data, name='json_topology_data'), url(r'^topology.yaml$', views.yaml_topology_data, name='json_topology_data'), url(r'^$', views.index, name='index'), diff --git a/awx/network_ui/views.py b/awx/network_ui/views.py index 9c72925e63..1f52179c52 100644 --- a/awx/network_ui/views.py +++ b/awx/network_ui/views.py @@ -6,7 +6,7 @@ import yaml # Create your views here. -from .models import Topology +from .models import Topology, FSMTrace from .serializers import topology_data @@ -35,3 +35,24 @@ def yaml_topology_data(request): else: return HttpResponseBadRequest(form.errors) + +class FSMTraceForm(forms.Form): + topology_id = forms.IntegerField() + trace_id = forms.IntegerField() + client_id = forms.IntegerField() + + +def download_trace(request): + form = FSMTraceForm(request.GET) + if form.is_valid(): + topology_id = form.cleaned_data['topology_id'] + trace_id = form.cleaned_data['trace_id'] + client_id = form.cleaned_data['client_id'] + data = list(FSMTrace.objects.filter(trace_session_id=trace_id, + client_id=client_id).order_by('order').values()) + response = HttpResponse(yaml.safe_dump(data, default_flow_style=False), + content_type="application/force-download") + response['Content-Disposition'] = 'attachment; filename="trace_{0}_{1}_{2}.yml"'.format(topology_id, client_id, trace_id) + return response + else: + return HttpResponse(form.errors)