mirror of
https://github.com/ansible/awx.git
synced 2026-01-14 11:20:39 -03:30
Adds toolbox to network UI
* Calls API to get inventory * Adds CopySite message * Adds Toolbox and ToolboxItem model design * Add Toolbox and ToolboxItem tables * Sends toolbox items to client from server on connect
This commit is contained in:
parent
c79ef60d8b
commit
6f1000cd94
@ -28,6 +28,10 @@ from awx.network_ui.models import Stream
|
||||
|
||||
from awx.network_ui.models import Process
|
||||
|
||||
from awx.network_ui.models import Toolbox
|
||||
|
||||
from awx.network_ui.models import ToolboxItem
|
||||
|
||||
|
||||
class DeviceAdmin(admin.ModelAdmin):
|
||||
fields = ('topology', 'name', 'x', 'y', 'id', 'type', 'interface_id_seq', 'process_id_seq',)
|
||||
@ -139,3 +143,19 @@ class ProcessAdmin(admin.ModelAdmin):
|
||||
|
||||
|
||||
admin.site.register(Process, ProcessAdmin)
|
||||
|
||||
|
||||
class ToolboxAdmin(admin.ModelAdmin):
|
||||
fields = ('name',)
|
||||
raw_id_fields = ()
|
||||
|
||||
|
||||
admin.site.register(Toolbox, ToolboxAdmin)
|
||||
|
||||
|
||||
class ToolboxItemAdmin(admin.ModelAdmin):
|
||||
fields = ('toolbox', 'data',)
|
||||
raw_id_fields = ('toolbox',)
|
||||
|
||||
|
||||
admin.site.register(ToolboxItem, ToolboxItemAdmin)
|
||||
|
||||
@ -6,6 +6,7 @@ from awx.network_ui.models import Group as DeviceGroup
|
||||
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.serializers import yaml_serialize_topology
|
||||
import urlparse
|
||||
from django.db.models import Q
|
||||
@ -382,14 +383,19 @@ class _Persistence(object):
|
||||
device_map = dict(Device.objects
|
||||
.filter(topology_id=topology_id, id__in=[stream['from_id'], stream['to_id']])
|
||||
.values_list('id', 'pk'))
|
||||
logger.info("onStreamCreate %s", stream)
|
||||
Stream.objects.get_or_create(id=stream['id'],
|
||||
label=stream['label'],
|
||||
label='',
|
||||
from_device_id=device_map[stream['from_id']],
|
||||
to_device_id=device_map[stream['to_id']])
|
||||
(Topology.objects
|
||||
.filter(topology_id=topology_id, stream_id_seq__lt=stream['id'])
|
||||
.update(stream_id_seq=stream['id']))
|
||||
|
||||
def onCopySite(self, site, topology_id, client_id):
|
||||
site_toolbox, _ = Toolbox.objects.get_or_create(name="Site")
|
||||
ToolboxItem(toolbox=site_toolbox, data=json.dumps(site['site'])).save()
|
||||
|
||||
def onDeviceSelected(self, message_value, topology_id, client_id):
|
||||
'Ignore DeviceSelected messages'
|
||||
pass
|
||||
@ -460,6 +466,7 @@ class _Persistence(object):
|
||||
onKeyEvent = write_event
|
||||
|
||||
def onGroupCreate(self, group, topology_id, client_id):
|
||||
logger.info("GroupCreate %s %s %s", group['id'], group['name'], group['type'])
|
||||
group = transform_dict(dict(x1='x1',
|
||||
y1='y1',
|
||||
x2='x2',
|
||||
@ -775,6 +782,14 @@ def ws_connect(message):
|
||||
message.reply_channel.send({"text": json.dumps(["Topology", topology_data])})
|
||||
send_snapshot(message.reply_channel, topology_id)
|
||||
send_history(message.reply_channel, topology_id)
|
||||
send_toolboxes(message.reply_channel)
|
||||
|
||||
|
||||
def send_toolboxes(channel):
|
||||
for toolbox_item in ToolboxItem.objects.filter(toolbox__name__in=['Process', 'Device', 'Rack', 'Site']).values('toolbox__name', 'data'):
|
||||
item = dict(toolbox_name=toolbox_item['toolbox__name'],
|
||||
data=toolbox_item['data'])
|
||||
channel.send({"text": json.dumps(["ToolboxItem", item])})
|
||||
|
||||
|
||||
def send_snapshot(channel, topology_id):
|
||||
@ -921,7 +936,10 @@ def make_sheet(data, column_headers=[]):
|
||||
|
||||
sheet = []
|
||||
|
||||
n_columns = max([len(x) for x in data]) - 1
|
||||
if len(data):
|
||||
n_columns = max([len(x) for x in data]) - 1
|
||||
else:
|
||||
n_columns = 0
|
||||
|
||||
row_i = 0
|
||||
sheet.append([dict(value=x, editable=False) for x in list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")[0:n_columns]])
|
||||
|
||||
@ -297,6 +297,29 @@ models:
|
||||
name: Process
|
||||
x: 654
|
||||
y: 778
|
||||
- fields:
|
||||
- name: toolbox_id
|
||||
pk: true
|
||||
type: AutoField
|
||||
- len: 200
|
||||
name: name
|
||||
type: CharField
|
||||
name: Toolbox
|
||||
x: -222
|
||||
y: 627
|
||||
- fields:
|
||||
- name: toolbox_item_id
|
||||
pk: true
|
||||
type: AutoField
|
||||
- name: toolbox
|
||||
ref: Toolbox
|
||||
ref_field: toolbox_id
|
||||
type: ForeignKey
|
||||
- name: data
|
||||
type: TextField
|
||||
name: ToolboxItem
|
||||
x: 54
|
||||
y: 664
|
||||
modules: []
|
||||
view:
|
||||
panX: 213.72955551921206
|
||||
|
||||
29
awx/network_ui/migrations/0021_toolbox_toolboxitem.py
Normal file
29
awx/network_ui/migrations/0021_toolbox_toolboxitem.py
Normal file
@ -0,0 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('network_ui', '0020_device_process_id_seq'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Toolbox',
|
||||
fields=[
|
||||
('toolbox_id', models.AutoField(serialize=False, primary_key=True)),
|
||||
('name', models.CharField(max_length=200)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ToolboxItem',
|
||||
fields=[
|
||||
('toolbox_item_id', models.AutoField(serialize=False, primary_key=True)),
|
||||
('data', models.TextField()),
|
||||
('toolbox', models.ForeignKey(to='network_ui.Toolbox')),
|
||||
],
|
||||
),
|
||||
]
|
||||
@ -142,3 +142,16 @@ class Process(models.Model):
|
||||
name = models.CharField(max_length=200,)
|
||||
type = models.CharField(max_length=200,)
|
||||
id = models.IntegerField(default=0)
|
||||
|
||||
|
||||
class Toolbox(models.Model):
|
||||
|
||||
toolbox_id = models.AutoField(primary_key=True,)
|
||||
name = models.CharField(max_length=200,)
|
||||
|
||||
|
||||
class ToolboxItem(models.Model):
|
||||
|
||||
toolbox_item_id = models.AutoField(primary_key=True,)
|
||||
toolbox = models.ForeignKey('Toolbox',)
|
||||
data = models.TextField()
|
||||
|
||||
@ -278,6 +278,12 @@ function PasteSite(group) {
|
||||
}
|
||||
exports.PasteSite = PasteSite;
|
||||
|
||||
function CopySite(site) {
|
||||
this.msg_type = "CopySite";
|
||||
this.site = site;
|
||||
}
|
||||
exports.CopySite = CopySite;
|
||||
|
||||
|
||||
function GroupMove(sender, id, x1, y1, x2, y2, previous_x1, previous_y1, previous_x2, previous_y2) {
|
||||
this.msg_type = "GroupMove";
|
||||
|
||||
@ -28,6 +28,16 @@ function Device(id, name, x, y, type) {
|
||||
}
|
||||
exports.Device = Device;
|
||||
|
||||
Device.prototype.toJSON = function () {
|
||||
return {id: this.id,
|
||||
name: this.name,
|
||||
x: this.x,
|
||||
y: this.y,
|
||||
type: this.type,
|
||||
interfaces: this.interfaces,
|
||||
processes: this.processes};
|
||||
};
|
||||
|
||||
Device.prototype.is_selected = function (x, y) {
|
||||
|
||||
return (x > this.x - this.width &&
|
||||
@ -51,6 +61,12 @@ function Interface(id, name) {
|
||||
}
|
||||
exports.Interface = Interface;
|
||||
|
||||
Interface.prototype.toJSON = function () {
|
||||
|
||||
return {id: this.id,
|
||||
name: this.name};
|
||||
};
|
||||
|
||||
Interface.prototype.remote_interface = function () {
|
||||
|
||||
if (this.link === null) {
|
||||
@ -192,6 +208,15 @@ function Link(id, from_device, to_device, from_interface, to_interface) {
|
||||
}
|
||||
exports.Link = Link;
|
||||
|
||||
Link.prototype.toJSON = function () {
|
||||
|
||||
return {from_device_id: this.from_device.id,
|
||||
to_device_id: this.to_device.id,
|
||||
from_interface_id: this.from_interface.id,
|
||||
to_interface_id: this.to_interface.id,
|
||||
name: this.name};
|
||||
};
|
||||
|
||||
Link.prototype.is_selected = function (x, y) {
|
||||
// Is the distance to the mouse location less than 25 if on the label side
|
||||
// or 5 on the other from the shortest line to the link?
|
||||
@ -349,6 +374,22 @@ function Group(id, name, type, x1, y1, x2, y2, selected) {
|
||||
}
|
||||
exports.Group = Group;
|
||||
|
||||
Group.prototype.toJSON = function () {
|
||||
|
||||
return {id: this.id,
|
||||
name: this.name,
|
||||
type: this.type,
|
||||
x1: this.x1,
|
||||
y1: this.y1,
|
||||
x2: this.x2,
|
||||
y2: this.y2,
|
||||
devices: this.devices,
|
||||
links: this.links,
|
||||
streams: this.streams,
|
||||
groups: this.groups};
|
||||
};
|
||||
|
||||
|
||||
Group.prototype.update_hightlighted = function (x, y) {
|
||||
|
||||
this.highlighted = this.is_highlighted(x, y);
|
||||
|
||||
@ -20,7 +20,7 @@ var messages = require('./messages.js');
|
||||
var svg_crowbar = require('../vendor/svg-crowbar.js');
|
||||
var ReconnectingWebSocket = require('reconnectingwebsocket');
|
||||
|
||||
var NetworkUIController = function($scope, $document, $location, $window) {
|
||||
var NetworkUIController = function($scope, $document, $location, $window, $http) {
|
||||
|
||||
window.scope = $scope;
|
||||
var i = 0;
|
||||
@ -30,6 +30,8 @@ var NetworkUIController = function($scope, $document, $location, $window) {
|
||||
|
||||
$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 || 0;
|
||||
|
||||
if (!$scope.disconnected) {
|
||||
$scope.control_socket = new ReconnectingWebSocket("ws://" + window.location.host + "/network_ui/topology?topology_id=" + $scope.topology_id,
|
||||
@ -139,19 +141,26 @@ var NetworkUIController = function($scope, $document, $location, $window) {
|
||||
|
||||
//Inventory Toolbox Setup
|
||||
$scope.inventory_toolbox = new models.ToolBox(0, 'Inventory', 'device', 10, 200, 150, $scope.graph.height - 200 - 100);
|
||||
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router6', 0, 0, 'router'));
|
||||
$scope.inventory_toolbox.items.push(new models.Device(0, 'Switch6', 0, 0, 'switch'));
|
||||
$scope.inventory_toolbox.items.push(new models.Device(0, 'Host6', 0, 0, 'host'));
|
||||
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router7', 0, 0, 'router'));
|
||||
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router8', 0, 0, 'router'));
|
||||
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router9', 0, 0, 'router'));
|
||||
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router10', 0, 0, 'router'));
|
||||
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router11', 0, 0, 'router'));
|
||||
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router12', 0, 0, 'router'));
|
||||
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router13', 0, 0, 'router'));
|
||||
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router14', 0, 0, 'router'));
|
||||
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router15', 0, 0, 'router'));
|
||||
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router16', 0, 0, 'router'));
|
||||
if (!$scope.disconnected) {
|
||||
$http.get('/api/v2/inventories/' + $scope.inventory_id + '/hosts/?format=json')
|
||||
.then(function(response) {
|
||||
console.log(response);
|
||||
|
||||
var host = null;
|
||||
var i = 0;
|
||||
function add_host (response) {
|
||||
console.log(response);
|
||||
var device = new models.Device(0, response.data.name, 0, 0, response.data.type);
|
||||
device.icon = true;
|
||||
$scope.inventory_toolbox.items.push(device);
|
||||
}
|
||||
for (i=0; i<response.data.results.length;i++) {
|
||||
host = response.data.results[i];
|
||||
$http.get('/api/v2/hosts/'+ host.id + '/variable_data?format=json')
|
||||
.then(add_host);
|
||||
}
|
||||
});
|
||||
}
|
||||
$scope.inventory_toolbox.spacing = 150;
|
||||
$scope.inventory_toolbox.enabled = true;
|
||||
$scope.inventory_toolbox_controller.toolbox = $scope.inventory_toolbox;
|
||||
@ -160,9 +169,6 @@ var NetworkUIController = function($scope, $document, $location, $window) {
|
||||
$scope.first_controller.handle_message("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);
|
||||
//Rack Toolbox Setup
|
||||
@ -1077,7 +1083,7 @@ var NetworkUIController = function($scope, $document, $location, $window) {
|
||||
$scope.link_id_seq = util.natural_numbers(data.link_id_seq);
|
||||
$scope.group_id_seq = util.natural_numbers(data.group_id_seq);
|
||||
$scope.device_id_seq = util.natural_numbers(data.device_id_seq);
|
||||
$location.search({topology_id: data.topology_id});
|
||||
$location.search({topology_id: data.topology_id, inventory_id: $scope.inventory_id});
|
||||
};
|
||||
|
||||
$scope.onDeviceSelected = function(data) {
|
||||
@ -1107,6 +1113,94 @@ var NetworkUIController = function($scope, $document, $location, $window) {
|
||||
}
|
||||
};
|
||||
|
||||
$scope.onToolboxItem = function (data) {
|
||||
if (data.toolbox_name === "Site") {
|
||||
var site = JSON.parse(data.data);
|
||||
console.log(site);
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
var site_copy = new models.Group(site.id,
|
||||
site.name,
|
||||
site.type,
|
||||
site.x1,
|
||||
site.y1,
|
||||
site.x2,
|
||||
site.y2,
|
||||
false);
|
||||
var device, device_copy;
|
||||
var process, process_copy;
|
||||
var intf, intf_copy;
|
||||
var device_map = {};
|
||||
for (i = 0; i < site.devices.length; i++) {
|
||||
device = site.devices[i];
|
||||
device_copy = new models.Device(device.id,
|
||||
device.name,
|
||||
device.x,
|
||||
device.y,
|
||||
device.type);
|
||||
device_map[device.id] = device_copy;
|
||||
device_copy.interface_map = {};
|
||||
site_copy.devices.push(device_copy);
|
||||
for(j=0; j < device.interfaces.length; j++) {
|
||||
intf = device.interfaces[j];
|
||||
intf_copy = new models.Interface(intf.id, intf.name);
|
||||
intf_copy.device = device_copy;
|
||||
device_copy.interfaces.push(intf_copy);
|
||||
device_copy.interface_map[intf.id] = intf_copy;
|
||||
}
|
||||
for(j=0; j < device.processes.length; j++) {
|
||||
process = device.processes[j];
|
||||
process_copy = new models.Process(process.id,
|
||||
process.name,
|
||||
process.type,
|
||||
process.x,
|
||||
process.y);
|
||||
process_copy.device = device;
|
||||
device_copy.processes.push(process_copy);
|
||||
}
|
||||
}
|
||||
console.log(device_map);
|
||||
var group, group_copy;
|
||||
for (i = 0; i < site.groups.length; i++) {
|
||||
group = site.groups[i];
|
||||
group_copy = new models.Group(group.id,
|
||||
group.name,
|
||||
group.type,
|
||||
group.x1,
|
||||
group.y1,
|
||||
group.x2,
|
||||
group.y2,
|
||||
false);
|
||||
site_copy.groups.push(group_copy);
|
||||
}
|
||||
var link, link_copy;
|
||||
for (i = 0; i < site.links.length; i++) {
|
||||
link = site.links[i];
|
||||
link_copy = new models.Link(link.id,
|
||||
device_map[link.from_device_id],
|
||||
device_map[link.to_device_id],
|
||||
device_map[link.from_device_id].interface_map[link.from_interface_id],
|
||||
device_map[link.to_device_id].interface_map[link.to_interface_id]);
|
||||
link_copy.name = link.name;
|
||||
device_map[link.from_device_id].interface_map[link.from_interface_id].link = link_copy;
|
||||
device_map[link.to_device_id].interface_map[link.to_interface_id].link = link_copy;
|
||||
site_copy.links.push(link_copy);
|
||||
}
|
||||
|
||||
var stream, stream_copy;
|
||||
|
||||
for(i = 0; i < site.streams.length;i++) {
|
||||
stream = site.streams[i];
|
||||
stream_copy = new models.Stream(stream.id,
|
||||
device_map[stream.from_device],
|
||||
device_map[stream.to_device],
|
||||
stream.label);
|
||||
site_copy.streams.push(stream_copy);
|
||||
}
|
||||
$scope.site_toolbox.items.push(site_copy);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.onSnapshot = function (data) {
|
||||
|
||||
//Erase the existing state
|
||||
|
||||
@ -208,6 +208,14 @@ _Ready.prototype.onPasteSite = function (controller, msg_type, message) {
|
||||
false);
|
||||
scope.groups.push(inner_group);
|
||||
group.groups.push(inner_group);
|
||||
c_messages.push(new messages.GroupCreate(scope.client_id,
|
||||
inner_group.id,
|
||||
inner_group.x1,
|
||||
inner_group.y1,
|
||||
inner_group.x2,
|
||||
inner_group.y2,
|
||||
inner_group.name,
|
||||
inner_group.type));
|
||||
}
|
||||
for(i=0; i< group.groups.length; i++) {
|
||||
group.groups[i].update_membership(scope.devices, scope.groups);
|
||||
@ -340,6 +348,8 @@ _Selected2.prototype.onCopySelected = function (controller) {
|
||||
group_copy.groups.push(inner_group);
|
||||
}
|
||||
|
||||
controller.scope.send_control_message(new messages.CopySite(group_copy));
|
||||
|
||||
controller.scope.site_toolbox.items.push(group_copy);
|
||||
}
|
||||
};
|
||||
|
||||
@ -389,6 +389,11 @@ _Present.prototype.onSnapshot = function(controller, msg_type, message) {
|
||||
controller.scope.onSnapshot(message);
|
||||
}
|
||||
};
|
||||
_Present.prototype.onToolboxItem = function(controller, msg_type, message) {
|
||||
if (message.sender !== controller.scope.client_id) {
|
||||
controller.scope.onToolboxItem(message);
|
||||
}
|
||||
};
|
||||
_Present.prototype.onid = function(controller, msg_type, message) {
|
||||
controller.scope.onClientId(message);
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user