diff --git a/awx/network_ui/CONTRIBUTING.md b/awx/network_ui/CONTRIBUTING.md index cd028ef1e1..106e5df02d 100644 --- a/awx/network_ui/CONTRIBUTING.md +++ b/awx/network_ui/CONTRIBUTING.md @@ -33,7 +33,7 @@ information about the interfaces on the devices and the links connecting those interfaces. These requirements determine the database schema needed for the network UI which -requires these models: Topology, Device, Interface, Link, Client, and TopologyInventory. +requires these models: Topology, Device, Interface, Link, and TopologyInventory. ![Models](designs/models.png) @@ -46,7 +46,6 @@ The models are: * Link - a physical connection between two devices to their respective interfaces * Topology - a collection of devices and links * TopologyInventory - a mapping between topologies and Tower inventories -* Client - a UI client session Network UI Websocket Protocol @@ -117,7 +116,7 @@ the database. Client Tracking --------------- -Each user session to the network UI canvas is tracked with the `Client` model. Multiple +Each user session to the network UI canvas is tracked with the `client_id` param. Multiple clients can view and interact with the network UI canvas at a time. They will see each other's edits to the canvas in real time. This works by broadcasting the canvas change events to all clients viewing the same topology. diff --git a/awx/network_ui/consumers.py b/awx/network_ui/consumers.py index d07b68b729..8b062883f3 100644 --- a/awx/network_ui/consumers.py +++ b/awx/network_ui/consumers.py @@ -1,13 +1,15 @@ # Copyright (c) 2017 Red Hat, Inc import channels from channels.auth import channel_session_user, channel_session_user_from_http -from awx.network_ui.models import Topology, Device, Link, Client, Interface +from awx.network_ui.models import Topology, Device, Link, Interface from awx.network_ui.models import TopologyInventory from awx.main.models.inventory import Inventory import urlparse from django.db.models import Q from collections import defaultdict import logging +import uuid +import six from awx.network_ui.utils import transform_dict @@ -245,11 +247,10 @@ def ws_connect(message): topology_id = topology.pk message.channel_session['topology_id'] = topology_id channels.Group("topology-%s" % topology_id).add(message.reply_channel) - client = Client() - client.save() - message.channel_session['client_id'] = client.pk - channels.Group("client-%s" % client.pk).add(message.reply_channel) - message.reply_channel.send({"text": json.dumps(["id", client.pk])}) + client_id = six.text_type(uuid.uuid4()) + message.channel_session['client_id'] = client_id + channels.Group("client-%s" % client_id).add(message.reply_channel) + message.reply_channel.send({"text": json.dumps(["id", client_id])}) message.reply_channel.send({"text": json.dumps(["topology_id", topology_id])}) topology_data = transform_dict(dict(id='topology_id', name='name', diff --git a/awx/network_ui/docs/models.yml b/awx/network_ui/docs/models.yml index 683dde4bfd..3176306249 100644 --- a/awx/network_ui/docs/models.yml +++ b/awx/network_ui/docs/models.yml @@ -86,13 +86,6 @@ models: name: Topology x: 111 y: 127 -- fields: - - name: client_id - pk: true - type: AutoField - name: Client - x: -162 - y: 282 - display: name fields: - name: interface_id diff --git a/awx/network_ui/migrations/0002_delete_client.py b/awx/network_ui/migrations/0002_delete_client.py new file mode 100644 index 0000000000..fe5708fa3c --- /dev/null +++ b/awx/network_ui/migrations/0002_delete_client.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.11 on 2018-05-30 17:18 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('network_ui', '0001_initial'), + ] + + operations = [ + migrations.DeleteModel( + name='Client', + ), + ] diff --git a/awx/network_ui/models.py b/awx/network_ui/models.py index 07d87e26cc..9712a6ce00 100644 --- a/awx/network_ui/models.py +++ b/awx/network_ui/models.py @@ -42,11 +42,6 @@ class Topology(models.Model): return self.name -class Client(models.Model): - - id = models.AutoField(primary_key=True,) - - class Interface(models.Model): id = models.AutoField(primary_key=True,) diff --git a/awx/network_ui/tests/functional/test_consumers.py b/awx/network_ui/tests/functional/test_consumers.py index f5d3d36173..e60f028651 100644 --- a/awx/network_ui/tests/functional/test_consumers.py +++ b/awx/network_ui/tests/functional/test_consumers.py @@ -8,7 +8,7 @@ patch('channels.auth.channel_session_user_from_http', lambda x: x).start() from awx.main.models import Inventory # noqa from awx.network_ui.consumers import parse_inventory_id, networking_events_dispatcher, send_snapshot # noqa -from awx.network_ui.models import Topology, Device, Link, Interface, TopologyInventory, Client # noqa +from awx.network_ui.models import Topology, Device, Link, Interface, TopologyInventory # noqa import awx # noqa import awx.network_ui # noqa import awx.network_ui.consumers # noqa @@ -181,7 +181,7 @@ def test_ws_connect_new_topology(): mock_user = mock.Mock() message = mock.MagicMock(user=mock_user) logger = logging.getLogger('awx.network_ui.consumers') - with mock.patch('awx.network_ui.consumers.Client') as client_mock,\ + with mock.patch('awx.network_ui.consumers.uuid') as client_mock,\ mock.patch('awx.network_ui.consumers.Topology') as topology_mock,\ mock.patch('channels.Group'),\ mock.patch('awx.network_ui.consumers.send_snapshot') as send_snapshot_mock,\ @@ -194,13 +194,13 @@ def test_ws_connect_new_topology(): mock.patch.object(Link, 'objects'),\ mock.patch.object(Interface, 'objects'),\ mock.patch.object(Inventory, 'objects') as inventory_objects: - client_mock.return_value.pk = 777 + client_mock.uuid4 = mock.MagicMock(return_value="777") topology_mock.return_value = Topology( name="topology", scale=1.0, panX=0, panY=0, pk=999) inventory_objects.get.return_value = mock.Mock(admin_role=[mock_user]) awx.network_ui.consumers.ws_connect(message) message.reply_channel.send.assert_has_calls([ - mock.call({'text': '["id", 777]'}), + mock.call({'text': '["id", "777"]'}), mock.call({'text': '["topology_id", 999]'}), mock.call( {'text': '["Topology", {"scale": 1.0, "name": "topology", "device_id_seq": 0, "panY": 0, "panX": 0, "topology_id": 999, "link_id_seq": 0}]'}), @@ -212,7 +212,7 @@ def test_ws_connect_existing_topology(): mock_user = mock.Mock() message = mock.MagicMock(user=mock_user) logger = logging.getLogger('awx.network_ui.consumers') - with mock.patch('awx.network_ui.consumers.Client') as client_mock,\ + with mock.patch('awx.network_ui.consumers.uuid') as client_mock,\ mock.patch('awx.network_ui.consumers.send_snapshot') as send_snapshot_mock,\ mock.patch('channels.Group'),\ mock.patch.object(logger, 'warning'),\ @@ -226,7 +226,7 @@ def test_ws_connect_existing_topology(): mock.patch.object(Inventory, 'objects') as inventory_objects: topology_inventory_objects_mock.filter.return_value.values_list.return_value = [ 1] - client_mock.return_value.pk = 888 + client_mock.uuid4 = mock.MagicMock(return_value="888") topology_objects_mock.get.return_value = Topology(pk=1001, id=1, name="topo", @@ -238,7 +238,7 @@ def test_ws_connect_existing_topology(): inventory_objects.get.return_value = mock.Mock(admin_role=[mock_user]) awx.network_ui.consumers.ws_connect(message) message.reply_channel.send.assert_has_calls([ - mock.call({'text': '["id", 888]'}), + mock.call({'text': '["id", "888"]'}), mock.call({'text': '["topology_id", 1001]'}), mock.call( {'text': '["Topology", {"scale": 1.0, "name": "topo", "device_id_seq": 1, "panY": 0, "panX": 0, "topology_id": 1001, "link_id_seq": 1}]'}),