Exporting Tosca from UI
Change-Id: Ie7e58ac5bd51a56d028daa1c1e2577e7723a8297
diff --git a/views/ngXosViews/serviceGrid/bower.json b/views/ngXosViews/serviceGrid/bower.json
index bae4e4d..18bd401 100644
--- a/views/ngXosViews/serviceGrid/bower.json
+++ b/views/ngXosViews/serviceGrid/bower.json
@@ -15,6 +15,9 @@
"tests"
],
"dependencies": {
+ "js-yaml": "~3.6.1",
+ "jszip": "Stuk/jszip#~3.0.0",
+ "file-saver": "eligrey/FileSaver.js#~1.3.2"
},
"devDependencies": {
"jquery": "2.1.4",
@@ -27,6 +30,7 @@
"lodash": "~4.11.1",
"bootstrap-css": "3.3.6",
"angular-chart.js": "~0.10.2",
- "d3": "~3.5.17"
+ "d3": "~3.5.17",
+ "angular-recursion": "~1.0.5"
}
}
diff --git a/views/ngXosViews/serviceGrid/karma.conf.js b/views/ngXosViews/serviceGrid/karma.conf.js
index 4123be9..44283c8 100644
--- a/views/ngXosViews/serviceGrid/karma.conf.js
+++ b/views/ngXosViews/serviceGrid/karma.conf.js
@@ -28,6 +28,7 @@
files: bowerComponents.concat([
'../../../xos/core/xoslib/static/js/vendor/ngXosVendor.js',
'../../../xos/core/xoslib/static/js/vendor/ngXosHelpers.js',
+ 'src/js/main.js',
'src/js/**/*.js',
'spec/**/*.mock.js',
'spec/**/*.test.js',
diff --git a/views/ngXosViews/serviceGrid/mocks/data/flavors.json b/views/ngXosViews/serviceGrid/mocks/data/flavors.json
new file mode 100644
index 0000000..251ccb6
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/mocks/data/flavors.json
@@ -0,0 +1,216 @@
+[
+ {
+ "humanReadableName": "m1.large",
+ "validators": {
+ "default": [],
+ "updated": [
+ "notBlank"
+ ],
+ "policed": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "deleted": [],
+ "description": [],
+ "no_policy": [],
+ "lazy_blocked": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "write_protect": [],
+ "flavor": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "order": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_sync": [],
+ "enacted": []
+ },
+ "id": 3,
+ "created": "2016-06-20T21:33:32.126894Z",
+ "updated": "2016-06-20T21:33:36.066908Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": true,
+ "no_policy": false,
+ "name": "m1.large",
+ "description": null,
+ "flavor": "m1.large",
+ "order": 0,
+ "default": false,
+ "deployments": [
+ 1
+ ]
+ },
+ {
+ "humanReadableName": "m1.medium",
+ "validators": {
+ "default": [],
+ "updated": [
+ "notBlank"
+ ],
+ "policed": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "deleted": [],
+ "description": [],
+ "no_policy": [],
+ "lazy_blocked": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "write_protect": [],
+ "flavor": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "order": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_sync": [],
+ "enacted": []
+ },
+ "id": 2,
+ "created": "2016-06-20T21:33:32.035528Z",
+ "updated": "2016-06-20T21:33:36.089834Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": true,
+ "no_policy": false,
+ "name": "m1.medium",
+ "description": null,
+ "flavor": "m1.medium",
+ "order": 0,
+ "default": false,
+ "deployments": [
+ 1
+ ]
+ },
+ {
+ "humanReadableName": "m1.small",
+ "validators": {
+ "default": [],
+ "updated": [
+ "notBlank"
+ ],
+ "policed": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "deleted": [],
+ "description": [],
+ "no_policy": [],
+ "lazy_blocked": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "write_protect": [],
+ "flavor": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "order": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_sync": [],
+ "enacted": []
+ },
+ "id": 1,
+ "created": "2016-06-20T21:33:31.974383Z",
+ "updated": "2016-06-20T21:33:36.106941Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": true,
+ "no_policy": false,
+ "name": "m1.small",
+ "description": null,
+ "flavor": "m1.small",
+ "order": 0,
+ "default": false,
+ "deployments": [
+ 1
+ ]
+ },
+ {
+ "humanReadableName": "m1.xlarge",
+ "validators": {
+ "default": [],
+ "updated": [
+ "notBlank"
+ ],
+ "policed": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "deleted": [],
+ "description": [],
+ "no_policy": [],
+ "lazy_blocked": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "write_protect": [],
+ "flavor": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "order": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_sync": [],
+ "enacted": []
+ },
+ "id": 4,
+ "created": "2016-06-20T21:33:36.234266Z",
+ "updated": "2016-06-20T21:33:36.234121Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": true,
+ "no_policy": false,
+ "name": "m1.xlarge",
+ "description": null,
+ "flavor": "m1.xlarge",
+ "order": 0,
+ "default": false,
+ "deployments": []
+ }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/mocks/data/images.json b/views/ngXosViews/serviceGrid/mocks/data/images.json
new file mode 100644
index 0000000..8a4fd83
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/mocks/data/images.json
@@ -0,0 +1,114 @@
+[
+ {
+ "humanReadableName": "trusty-server-multi-nic",
+ "validators": {
+ "updated": [
+ "notBlank"
+ ],
+ "policed": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "deleted": [],
+ "container_format": [
+ "notBlank"
+ ],
+ "no_policy": [],
+ "disk_format": [
+ "notBlank"
+ ],
+ "kind": [
+ "notBlank"
+ ],
+ "lazy_blocked": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "write_protect": [],
+ "tag": [],
+ "path": [],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_sync": [],
+ "enacted": []
+ },
+ "id": 2,
+ "created": "2016-06-20T21:29:37.969117Z",
+ "updated": "2016-06-20T21:29:37.968740Z",
+ "enacted": "2016-06-20T21:29:38.057186Z",
+ "policed": "2016-06-20T21:29:39.144781Z",
+ "backend_register": "{\"next_run\": 0, \"last_success\": 1466458178.081831, \"exponent\": 0}",
+ "backend_status": "1 - OK",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "name": "trusty-server-multi-nic",
+ "kind": "vm",
+ "disk_format": "raw",
+ "container_format": "bare",
+ "path": "/opt/xos/images/trusty-server-multi-nic.img",
+ "tag": null,
+ "deployments": []
+ },
+ {
+ "humanReadableName": "vsg-1.0",
+ "validators": {
+ "updated": [
+ "notBlank"
+ ],
+ "policed": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "deleted": [],
+ "container_format": [
+ "notBlank"
+ ],
+ "no_policy": [],
+ "disk_format": [
+ "notBlank"
+ ],
+ "kind": [
+ "notBlank"
+ ],
+ "lazy_blocked": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "write_protect": [],
+ "tag": [],
+ "path": [],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_sync": [],
+ "enacted": []
+ },
+ "id": 1,
+ "created": "2016-06-20T21:29:37.949039Z",
+ "updated": "2016-06-20T21:36:36.196635Z",
+ "enacted": "2016-06-20T21:36:56.463927Z",
+ "policed": "2016-06-20T21:36:37.125141Z",
+ "backend_register": "{\"next_run\": 0, \"last_success\": 1466458616.491853, \"exponent\": 0}",
+ "backend_status": "1 - OK",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "name": "vsg-1.0",
+ "kind": "vm",
+ "disk_format": "raw",
+ "container_format": "bare",
+ "path": "/opt/xos/images/vsg-1.0.img",
+ "tag": null,
+ "deployments": []
+ }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/mocks/data/instances.json b/views/ngXosViews/serviceGrid/mocks/data/instances.json
new file mode 100644
index 0000000..68a9620
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/mocks/data/instances.json
@@ -0,0 +1,89 @@
+[
+ {
+ "humanReadableName": "mysite_vsg-1",
+ "validators": {
+ "policed": [],
+ "creator": [],
+ "ip": [],
+ "image": [
+ "notBlank"
+ ],
+ "backend_register": [
+ "notBlank"
+ ],
+ "flavor": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "instance_name": [],
+ "slice": [
+ "notBlank"
+ ],
+ "no_sync": [],
+ "node": [
+ "notBlank"
+ ],
+ "userData": [],
+ "updated": [
+ "notBlank"
+ ],
+ "parent": [],
+ "deleted": [],
+ "lazy_blocked": [],
+ "deployment": [
+ "notBlank"
+ ],
+ "enacted": [],
+ "instance_uuid": [],
+ "numberCores": [
+ "notBlank"
+ ],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "isolation": [
+ "notBlank"
+ ],
+ "no_policy": [],
+ "instance_id": [],
+ "volumes": []
+ },
+ "id": 1,
+ "created": "2016-06-20T21:36:36.599139Z",
+ "updated": "2016-06-20T21:36:38.654961Z",
+ "enacted": "2016-06-20T21:37:09.416303Z",
+ "policed": "2016-06-20T21:36:40.179041Z",
+ "backend_register": "{\"next_run\": 0, \"last_success\": 1466458656.696624, \"exponent\": 0}",
+ "backend_status": "1 - OK",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "instance_id": "instance-00000001",
+ "instance_uuid": "6cdf8d0b-0468-4ce2-af07-b8d35e0e14cf",
+ "name": "mysite_vsg",
+ "instance_name": "mysite_vsg-1",
+ "ip": "192.168.122.140",
+ "image": 1,
+ "creator": 1,
+ "slice": 2,
+ "deployment": 1,
+ "node": 1,
+ "numberCores": 0,
+ "flavor": 1,
+ "userData": null,
+ "isolation": "vm",
+ "volumes": "/etc/dnsmasq.d,/etc/ufw",
+ "parent": null,
+ "networks": [
+ 1,
+ 2
+ ]
+ }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/mocks/data/networks.json b/views/ngXosViews/serviceGrid/mocks/data/networks.json
new file mode 100644
index 0000000..e581298
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/mocks/data/networks.json
@@ -0,0 +1,166 @@
+[
+ {
+ "humanReadableName": "management",
+ "validators": {
+ "router_id": [],
+ "policed": [],
+ "labels": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "start_ip": [],
+ "owner": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "subnet": [],
+ "subnet_id": [],
+ "end_ip": [],
+ "template": [
+ "notBlank"
+ ],
+ "no_sync": [],
+ "permit_all_slices": [],
+ "updated": [
+ "notBlank"
+ ],
+ "controller_url": [],
+ "controller_parameters": [],
+ "deleted": [],
+ "lazy_blocked": [],
+ "guaranteed_bandwidth": [
+ "notBlank"
+ ],
+ "enacted": [],
+ "autoconnect": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "network_id": [],
+ "topology_parameters": [],
+ "ports": []
+ },
+ "id": 1,
+ "created": "2016-06-20T21:36:32.006043Z",
+ "updated": "2016-06-20T21:36:32.039571Z",
+ "enacted": null,
+ "policed": "2016-06-20T21:36:32.389397Z",
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "name": "management",
+ "template": 4,
+ "subnet": "172.27.0.0/24",
+ "ports": null,
+ "labels": null,
+ "owner": 1,
+ "guaranteed_bandwidth": 0,
+ "permit_all_slices": true,
+ "topology_parameters": null,
+ "controller_url": null,
+ "controller_parameters": null,
+ "network_id": null,
+ "router_id": null,
+ "subnet_id": null,
+ "autoconnect": false,
+ "slices": [
+ 2
+ ],
+ "instances": [
+ 1
+ ],
+ "routers": []
+ },
+ {
+ "humanReadableName": "mysite_vsg-access",
+ "validators": {
+ "router_id": [],
+ "policed": [],
+ "labels": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "start_ip": [],
+ "owner": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "subnet": [],
+ "subnet_id": [],
+ "end_ip": [],
+ "template": [
+ "notBlank"
+ ],
+ "no_sync": [],
+ "permit_all_slices": [],
+ "updated": [
+ "notBlank"
+ ],
+ "controller_url": [],
+ "controller_parameters": [],
+ "deleted": [],
+ "lazy_blocked": [],
+ "guaranteed_bandwidth": [
+ "notBlank"
+ ],
+ "enacted": [],
+ "autoconnect": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "network_id": [],
+ "topology_parameters": [],
+ "ports": []
+ },
+ "id": 2,
+ "created": "2016-06-20T21:36:36.439706Z",
+ "updated": "2016-06-20T21:36:36.456977Z",
+ "enacted": null,
+ "policed": "2016-06-20T21:36:37.419444Z",
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "name": "mysite_vsg-access",
+ "template": 2,
+ "subnet": "",
+ "ports": null,
+ "labels": null,
+ "owner": 2,
+ "guaranteed_bandwidth": 0,
+ "permit_all_slices": true,
+ "topology_parameters": null,
+ "controller_url": null,
+ "controller_parameters": null,
+ "network_id": null,
+ "router_id": null,
+ "subnet_id": null,
+ "autoconnect": false,
+ "slices": [
+ 2
+ ],
+ "instances": [
+ 1
+ ],
+ "routers": []
+ }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/mocks/data/networktemplates.json b/views/ngXosViews/serviceGrid/mocks/data/networktemplates.json
new file mode 100644
index 0000000..c36a401
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/mocks/data/networktemplates.json
@@ -0,0 +1,262 @@
+[
+ {
+ "humanReadableName": "Public shared IPv4",
+ "validators": {
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "access": [],
+ "shared_network_name": [],
+ "controller_kind": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "visibility": [
+ "notBlank"
+ ],
+ "lazy_blocked": [],
+ "guaranteed_bandwidth": [
+ "notBlank"
+ ],
+ "translation": [
+ "notBlank"
+ ],
+ "topology_kind": [
+ "notBlank"
+ ],
+ "enacted": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "no_sync": [],
+ "shared_network_id": []
+ },
+ "id": 1,
+ "created": "2016-06-23T20:14:16.126918Z",
+ "updated": "2016-06-23T20:14:16.126754Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "name": "Public shared IPv4",
+ "description": null,
+ "guaranteed_bandwidth": 0,
+ "visibility": "private",
+ "translation": "NAT",
+ "access": null,
+ "shared_network_name": "nat-net",
+ "shared_network_id": null,
+ "topology_kind": "bigswitch",
+ "controller_kind": null
+ },
+ {
+ "humanReadableName": "Public dedicated IPv4",
+ "validators": {
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "access": [],
+ "shared_network_name": [],
+ "controller_kind": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "visibility": [
+ "notBlank"
+ ],
+ "lazy_blocked": [],
+ "guaranteed_bandwidth": [
+ "notBlank"
+ ],
+ "translation": [
+ "notBlank"
+ ],
+ "topology_kind": [
+ "notBlank"
+ ],
+ "enacted": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "no_sync": [],
+ "shared_network_id": []
+ },
+ "id": 3,
+ "created": "2016-06-23T20:14:16.202765Z",
+ "updated": "2016-06-23T20:14:16.202562Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "name": "Public dedicated IPv4",
+ "description": null,
+ "guaranteed_bandwidth": 0,
+ "visibility": "public",
+ "translation": "none",
+ "access": null,
+ "shared_network_name": "ext-net",
+ "shared_network_id": null,
+ "topology_kind": "bigswitch",
+ "controller_kind": null
+ },
+ {
+ "humanReadableName": "management_template",
+ "validators": {
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "access": [],
+ "shared_network_name": [],
+ "controller_kind": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "visibility": [
+ "notBlank"
+ ],
+ "lazy_blocked": [],
+ "guaranteed_bandwidth": [
+ "notBlank"
+ ],
+ "translation": [
+ "notBlank"
+ ],
+ "topology_kind": [
+ "notBlank"
+ ],
+ "enacted": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "no_sync": [],
+ "shared_network_id": []
+ },
+ "id": 4,
+ "created": "2016-06-23T20:18:19.778090Z",
+ "updated": "2016-06-23T20:18:19.777887Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "name": "management_template",
+ "description": null,
+ "guaranteed_bandwidth": 0,
+ "visibility": "private",
+ "translation": "none",
+ "access": null,
+ "shared_network_name": null,
+ "shared_network_id": null,
+ "topology_kind": "bigswitch",
+ "controller_kind": null
+ },
+ {
+ "humanReadableName": "Private",
+ "validators": {
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "access": [],
+ "shared_network_name": [],
+ "controller_kind": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "visibility": [
+ "notBlank"
+ ],
+ "lazy_blocked": [],
+ "guaranteed_bandwidth": [
+ "notBlank"
+ ],
+ "translation": [
+ "notBlank"
+ ],
+ "topology_kind": [
+ "notBlank"
+ ],
+ "enacted": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "no_sync": [],
+ "shared_network_id": []
+ },
+ "id": 2,
+ "created": "2016-06-23T20:14:16.178408Z",
+ "updated": "2016-06-23T20:18:24.072523Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "name": "Private",
+ "description": null,
+ "guaranteed_bandwidth": 0,
+ "visibility": "private",
+ "translation": "none",
+ "access": null,
+ "shared_network_name": null,
+ "shared_network_id": null,
+ "topology_kind": "bigswitch",
+ "controller_kind": null
+ }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/mocks/data/node.json b/views/ngXosViews/serviceGrid/mocks/data/node.json
new file mode 100644
index 0000000..b92923f
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/mocks/data/node.json
@@ -0,0 +1,48 @@
+[
+ {
+ "humanReadableName": "nova-compute-1",
+ "validators": {
+ "updated": [
+ "notBlank"
+ ],
+ "policed": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "deleted": [],
+ "no_policy": [],
+ "site": [],
+ "lazy_blocked": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "write_protect": [],
+ "site_deployment": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_sync": [],
+ "enacted": []
+ },
+ "id": 1,
+ "created": "2016-06-20T21:33:43.532833Z",
+ "updated": "2016-06-20T21:37:46.435545Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": true,
+ "no_policy": false,
+ "name": "nova-compute-1",
+ "site_deployment": 1,
+ "site": 1,
+ "nodelabels": []
+ }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/mocks/data/services.json b/views/ngXosViews/serviceGrid/mocks/data/services.json
new file mode 100644
index 0000000..f961a3c
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/mocks/data/services.json
@@ -0,0 +1,514 @@
+[
+ {
+ "humanReadableName": "fabric",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "view_url": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "private_key_fn": [],
+ "icon_url": [],
+ "no_sync": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "lazy_blocked": [],
+ "versionNumber": [],
+ "service_specific_id": [],
+ "enacted": [],
+ "public_key": [],
+ "kind": [
+ "notBlank"
+ ],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "enabled": [],
+ "controller": [],
+ "published": []
+ },
+ "id": 3,
+ "created": "2016-06-20T21:35:56.788935Z",
+ "updated": "2016-06-20T21:35:56.788499Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "description": null,
+ "enabled": true,
+ "kind": "fabric",
+ "name": "fabric",
+ "versionNumber": null,
+ "published": true,
+ "view_url": "/admin/fabric/fabricservice/$id$/",
+ "icon_url": null,
+ "public_key": null,
+ "private_key_fn": null,
+ "service_specific_id": null,
+ "service_specific_attribute": null
+ },
+ {
+ "humanReadableName": "ONOS_Fabric",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "view_url": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "private_key_fn": [],
+ "icon_url": [],
+ "no_sync": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "lazy_blocked": [],
+ "versionNumber": [],
+ "service_specific_id": [],
+ "enacted": [],
+ "public_key": [],
+ "kind": [
+ "notBlank"
+ ],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "enabled": [],
+ "controller": [],
+ "published": []
+ },
+ "id": 4,
+ "created": "2016-06-20T21:35:56.810806Z",
+ "updated": "2016-06-20T21:35:56.810649Z",
+ "enacted": "2016-06-20T21:36:04.658726Z",
+ "policed": null,
+ "backend_register": "{\"next_run\": 0, \"last_success\": 1466458564.69207, \"exponent\": 0}",
+ "backend_status": "1 - OK",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "description": null,
+ "enabled": true,
+ "kind": "onos",
+ "name": "ONOS_Fabric",
+ "versionNumber": null,
+ "published": true,
+ "view_url": "/admin/onos/onosservice/$id$/",
+ "icon_url": null,
+ "public_key": null,
+ "private_key_fn": null,
+ "service_specific_id": null,
+ "service_specific_attribute": "{\"no_container\": true, \"rest_hostname\": \"onos-fabric\"}"
+ },
+ {
+ "humanReadableName": "vrouter",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "view_url": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "private_key_fn": [],
+ "icon_url": [],
+ "no_sync": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "lazy_blocked": [],
+ "versionNumber": [],
+ "service_specific_id": [],
+ "enacted": [],
+ "public_key": [],
+ "kind": [
+ "notBlank"
+ ],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "enabled": [],
+ "controller": [],
+ "published": []
+ },
+ "id": 5,
+ "created": "2016-06-20T21:36:36.240269Z",
+ "updated": "2016-06-20T21:36:36.240062Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "description": null,
+ "enabled": true,
+ "kind": "vROUTER",
+ "name": "vrouter",
+ "versionNumber": null,
+ "published": true,
+ "view_url": "/admin/vrouter/vrouterservice/$id$/",
+ "icon_url": null,
+ "public_key": null,
+ "private_key_fn": null,
+ "service_specific_id": null,
+ "service_specific_attribute": null
+ },
+ {
+ "humanReadableName": "vsg",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "view_url": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "private_key_fn": [],
+ "icon_url": [],
+ "no_sync": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "lazy_blocked": [],
+ "versionNumber": [],
+ "service_specific_id": [],
+ "enacted": [],
+ "public_key": [],
+ "kind": [
+ "notBlank"
+ ],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "enabled": [],
+ "controller": [],
+ "published": []
+ },
+ "id": 6,
+ "created": "2016-06-20T21:36:36.262734Z",
+ "updated": "2016-06-20T21:36:36.262503Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "description": null,
+ "enabled": true,
+ "kind": "vCPE",
+ "name": "vsg",
+ "versionNumber": null,
+ "published": true,
+ "view_url": "/admin/cord/vsgservice/$id$/",
+ "icon_url": null,
+ "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCl1k9r1G491+ClISp6JOKlNmgBSV5YAvw2Ulh5Mj7XUgLatjHIBID2Ue54kAbCP48LVIAhqVFClPC7PtfVQY9+3mKi+LUJCgkkjR+6IlK/8eVzr1i3BvhLbtifrhKCvdL+d/5Tzxl8C8qCWfnJhVTqGRmVGBDFf4SukCjxF5CMG1naSlkgrINlMNc34IfQ2UAxRSscsEaMiijDQFBwGhJLQzef0r9vfIycnv3Ua/xQ5Pjqtcy/Go6K849wsNNUQ4yMgaUWZ8tmwFuqu4nFC2lI/H8EZN4NBejjMnJs3F6IMb0xe45/r7TXvWEpZ1c/nNwrvOPi/U44VkwMgp/EcRgV smbaker@node.smbaker-xos-test.xos-pg0.wisc.cloudlab.us\n",
+ "private_key_fn": "/opt/xos/services/vsg/keys/vsg_rsa",
+ "service_specific_id": null,
+ "service_specific_attribute": "{\"backend_network_label\": \"hpc_client\"}"
+ },
+ {
+ "humanReadableName": "volt",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "view_url": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "private_key_fn": [],
+ "icon_url": [],
+ "no_sync": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "lazy_blocked": [],
+ "versionNumber": [],
+ "service_specific_id": [],
+ "enacted": [],
+ "public_key": [],
+ "kind": [
+ "notBlank"
+ ],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "enabled": [],
+ "controller": [],
+ "published": []
+ },
+ "id": 7,
+ "created": "2016-06-20T21:36:36.468811Z",
+ "updated": "2016-06-20T21:36:36.468645Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "description": null,
+ "enabled": true,
+ "kind": "vOLT",
+ "name": "volt",
+ "versionNumber": null,
+ "published": true,
+ "view_url": "/admin/cord/voltservice/$id$/",
+ "icon_url": null,
+ "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCl1k9r1G491+ClISp6JOKlNmgBSV5YAvw2Ulh5Mj7XUgLatjHIBID2Ue54kAbCP48LVIAhqVFClPC7PtfVQY9+3mKi+LUJCgkkjR+6IlK/8eVzr1i3BvhLbtifrhKCvdL+d/5Tzxl8C8qCWfnJhVTqGRmVGBDFf4SukCjxF5CMG1naSlkgrINlMNc34IfQ2UAxRSscsEaMiijDQFBwGhJLQzef0r9vfIycnv3Ua/xQ5Pjqtcy/Go6K849wsNNUQ4yMgaUWZ8tmwFuqu4nFC2lI/H8EZN4NBejjMnJs3F6IMb0xe45/r7TXvWEpZ1c/nNwrvOPi/U44VkwMgp/EcRgV smbaker@node.smbaker-xos-test.xos-pg0.wisc.cloudlab.us\n",
+ "private_key_fn": "/opt/xos/services/volt/keys/volt_rsa",
+ "service_specific_id": null,
+ "service_specific_attribute": null
+ },
+ {
+ "humanReadableName": "vtr",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "view_url": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "private_key_fn": [],
+ "icon_url": [],
+ "no_sync": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "lazy_blocked": [],
+ "versionNumber": [],
+ "service_specific_id": [],
+ "enacted": [],
+ "public_key": [],
+ "kind": [
+ "notBlank"
+ ],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "enabled": [],
+ "controller": [],
+ "published": []
+ },
+ "id": 8,
+ "created": "2016-06-20T21:36:37.129713Z",
+ "updated": "2016-06-20T21:36:37.129433Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "description": null,
+ "enabled": true,
+ "kind": "vTR",
+ "name": "vtr",
+ "versionNumber": null,
+ "published": true,
+ "view_url": "/admin/vtr/vtrservice/$id$/",
+ "icon_url": null,
+ "public_key": null,
+ "private_key_fn": null,
+ "service_specific_id": null,
+ "service_specific_attribute": null
+ },
+ {
+ "humanReadableName": "vtn",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "view_url": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "private_key_fn": [],
+ "icon_url": [],
+ "no_sync": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "lazy_blocked": [],
+ "versionNumber": [],
+ "service_specific_id": [],
+ "enacted": [],
+ "public_key": [],
+ "kind": [
+ "notBlank"
+ ],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "enabled": [],
+ "controller": [],
+ "published": []
+ },
+ "id": 2,
+ "created": "2016-06-20T21:35:51.964599Z",
+ "updated": "2016-06-20T21:37:46.469766Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "description": null,
+ "enabled": true,
+ "kind": "VTN",
+ "name": "vtn",
+ "versionNumber": null,
+ "published": true,
+ "view_url": "/admin/vtn/vtnservice/$id$/",
+ "icon_url": null,
+ "public_key": null,
+ "private_key_fn": null,
+ "service_specific_id": null,
+ "service_specific_attribute": "{\"sshUser\": \"root\", \"xosEndpoint\": \"http://xos/\", \"xosPassword\": \"letmein\", \"sshKeyFile\": \"/root/node_key\", \"xosUser\": \"padmin@vicci.org\", \"ovsdbPort\": \"6641\", \"sshPort\": \"22\", \"localManagementIp\": \"172.27.0.1/24\", \"privateGatewayMac\": \"00:00:00:00:00:01\"}"
+ },
+ {
+ "humanReadableName": "ONOS_CORD",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "view_url": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "private_key_fn": [],
+ "icon_url": [],
+ "no_sync": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "lazy_blocked": [],
+ "versionNumber": [],
+ "service_specific_id": [],
+ "enacted": [],
+ "public_key": [],
+ "kind": [
+ "notBlank"
+ ],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "enabled": [],
+ "controller": [],
+ "published": []
+ },
+ "id": 1,
+ "created": "2016-06-20T21:35:51.892027Z",
+ "updated": "2016-06-20T21:37:46.417265Z",
+ "enacted": "2016-06-20T21:37:54.037851Z",
+ "policed": null,
+ "backend_register": "{\"next_run\": 0, \"last_success\": 1466458674.061194, \"exponent\": 0}",
+ "backend_status": "1 - OK",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "description": null,
+ "enabled": true,
+ "kind": "onos",
+ "name": "ONOS_CORD",
+ "versionNumber": null,
+ "published": true,
+ "view_url": "/admin/onos/onosservice/$id$/",
+ "icon_url": null,
+ "public_key": null,
+ "private_key_fn": null,
+ "service_specific_id": null,
+ "service_specific_attribute": "{\"no_container\": true, \"rest_hostname\": \"onos-cord\"}"
+ }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/mocks/data/sites.json b/views/ngXosViews/serviceGrid/mocks/data/sites.json
new file mode 100644
index 0000000..bd0ba95
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/mocks/data/sites.json
@@ -0,0 +1,72 @@
+[
+ {
+ "humanReadableName": "mysite",
+ "validators": {
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "site_url": [
+ "url"
+ ],
+ "location": [
+ "notBlank"
+ ],
+ "hosts_nodes": [],
+ "no_sync": [],
+ "abbreviated_name": [
+ "notBlank"
+ ],
+ "updated": [
+ "notBlank"
+ ],
+ "deleted": [],
+ "lazy_blocked": [],
+ "latitude": [],
+ "is_public": [],
+ "enacted": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "enabled": [],
+ "longitude": [],
+ "hosts_users": [],
+ "login_base": [
+ "notBlank"
+ ]
+ },
+ "id": 1,
+ "created": "2016-06-20T21:33:36.116579Z",
+ "updated": "2016-06-20T21:36:36.210629Z",
+ "enacted": null,
+ "policed": "2016-06-20T21:36:37.091400Z",
+ "backend_register": "{}",
+ "backend_status": "1 - OK",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "name": "mysite",
+ "site_url": "http://xosproject.org/",
+ "enabled": true,
+ "hosts_nodes": true,
+ "hosts_users": true,
+ "location": null,
+ "longitude": null,
+ "latitude": null,
+ "login_base": "mysite",
+ "is_public": true,
+ "abbreviated_name": "",
+ "deployments": [
+ 1
+ ]
+ }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/mocks/data/slices.json b/views/ngXosViews/serviceGrid/mocks/data/slices.json
new file mode 100644
index 0000000..2f4d00c
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/mocks/data/slices.json
@@ -0,0 +1,163 @@
+[
+ {
+ "humanReadableName": "mysite_management",
+ "validators": {
+ "default_flavor": [],
+ "policed": [],
+ "creator": [],
+ "site": [
+ "notBlank"
+ ],
+ "max_instances": [
+ "notBlank"
+ ],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "network": [],
+ "service": [],
+ "default_isolation": [
+ "notBlank"
+ ],
+ "no_sync": [],
+ "exposed_ports": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "slice_url": [
+ "url"
+ ],
+ "serviceClass": [],
+ "lazy_blocked": [],
+ "omf_friendly": [],
+ "mount_data_sets": [],
+ "default_node": [],
+ "enacted": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "enabled": [],
+ "default_image": []
+ },
+ "id": 1,
+ "created": "2016-06-20T21:36:31.979507Z",
+ "updated": "2016-06-20T21:36:38.635976Z",
+ "enacted": null,
+ "policed": "2016-06-20T21:36:38.787528Z",
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "name": "mysite_management",
+ "enabled": true,
+ "omf_friendly": false,
+ "description": "",
+ "slice_url": "",
+ "site": 1,
+ "max_instances": 10,
+ "service": null,
+ "network": "noauto",
+ "exposed_ports": null,
+ "serviceClass": null,
+ "creator": 1,
+ "default_flavor": null,
+ "default_image": null,
+ "mount_data_sets": "GenBank",
+ "default_isolation": "vm",
+ "networks": []
+ },
+ {
+ "humanReadableName": "mysite_vsg",
+ "validators": {
+ "default_flavor": [],
+ "policed": [],
+ "creator": [],
+ "site": [
+ "notBlank"
+ ],
+ "max_instances": [
+ "notBlank"
+ ],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "network": [],
+ "service": [],
+ "default_isolation": [
+ "notBlank"
+ ],
+ "no_sync": [],
+ "exposed_ports": [],
+ "updated": [
+ "notBlank"
+ ],
+ "description": [],
+ "deleted": [],
+ "slice_url": [
+ "url"
+ ],
+ "serviceClass": [],
+ "lazy_blocked": [],
+ "omf_friendly": [],
+ "mount_data_sets": [],
+ "default_node": [],
+ "enacted": [],
+ "name": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "no_policy": [],
+ "enabled": [],
+ "default_image": []
+ },
+ "id": 2,
+ "created": "2016-06-20T21:36:36.290539Z",
+ "updated": "2016-06-20T21:36:38.625760Z",
+ "enacted": null,
+ "policed": "2016-06-20T21:36:40.119502Z",
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "name": "mysite_vsg",
+ "enabled": true,
+ "omf_friendly": false,
+ "description": "",
+ "slice_url": "",
+ "site": 1,
+ "max_instances": 10,
+ "service": 6,
+ "network": "noauto",
+ "exposed_ports": null,
+ "serviceClass": null,
+ "creator": 1,
+ "default_flavor": null,
+ "default_image": 1,
+ "mount_data_sets": "GenBank",
+ "default_isolation": "vm",
+ "networks": [
+ 2,
+ 1
+ ]
+ }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/mocks/data/tenants.json b/views/ngXosViews/serviceGrid/mocks/data/tenants.json
new file mode 100644
index 0000000..2739c9a
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/mocks/data/tenants.json
@@ -0,0 +1,612 @@
+[
+ {
+ "humanReadableName": "coarse-tenant-3",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_policy": [],
+ "subscriber_service": [],
+ "subscriber_tenant": [],
+ "no_sync": [],
+ "connect_method": [
+ "notBlank"
+ ],
+ "updated": [
+ "notBlank"
+ ],
+ "deleted": [],
+ "lazy_blocked": [],
+ "service_specific_id": [],
+ "subscriber_root": [],
+ "subscriber_user": [],
+ "enacted": [],
+ "kind": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "subscriber_network": [],
+ "provider_service": [
+ "notBlank"
+ ]
+ },
+ "id": 3,
+ "created": "2016-06-20T21:36:36.274049Z",
+ "updated": "2016-06-20T21:36:36.273883Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "kind": "coarse",
+ "provider_service": 5,
+ "subscriber_service": 6,
+ "subscriber_tenant": null,
+ "subscriber_user": null,
+ "subscriber_root": null,
+ "subscriber_network": null,
+ "service_specific_id": null,
+ "service_specific_attribute": null,
+ "connect_method": "na"
+ },
+ {
+ "humanReadableName": "coarse-tenant-4",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_policy": [],
+ "subscriber_service": [],
+ "subscriber_tenant": [],
+ "no_sync": [],
+ "connect_method": [
+ "notBlank"
+ ],
+ "updated": [
+ "notBlank"
+ ],
+ "deleted": [],
+ "lazy_blocked": [],
+ "service_specific_id": [],
+ "subscriber_root": [],
+ "subscriber_user": [],
+ "enacted": [],
+ "kind": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "subscriber_network": [],
+ "provider_service": [
+ "notBlank"
+ ]
+ },
+ "id": 4,
+ "created": "2016-06-20T21:36:36.477159Z",
+ "updated": "2016-06-20T21:36:36.477018Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "kind": "coarse",
+ "provider_service": 6,
+ "subscriber_service": 7,
+ "subscriber_tenant": null,
+ "subscriber_user": null,
+ "subscriber_root": null,
+ "subscriber_network": null,
+ "service_specific_id": null,
+ "service_specific_attribute": null,
+ "connect_method": "na"
+ },
+ {
+ "humanReadableName": "vOLT-tenant-6",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_policy": [],
+ "subscriber_service": [],
+ "subscriber_tenant": [],
+ "no_sync": [],
+ "connect_method": [
+ "notBlank"
+ ],
+ "updated": [
+ "notBlank"
+ ],
+ "deleted": [],
+ "lazy_blocked": [],
+ "service_specific_id": [],
+ "subscriber_root": [],
+ "subscriber_user": [],
+ "enacted": [],
+ "kind": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "subscriber_network": [],
+ "provider_service": [
+ "notBlank"
+ ]
+ },
+ "id": 6,
+ "created": "2016-06-20T21:36:36.533209Z",
+ "updated": "2016-06-20T21:36:36.533060Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "kind": "vOLT",
+ "provider_service": 7,
+ "subscriber_service": null,
+ "subscriber_tenant": null,
+ "subscriber_user": null,
+ "subscriber_root": 1,
+ "subscriber_network": null,
+ "service_specific_id": "123",
+ "service_specific_attribute": null,
+ "connect_method": "na"
+ },
+ {
+ "humanReadableName": "vCPE-tenant-7",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_policy": [],
+ "subscriber_service": [],
+ "subscriber_tenant": [],
+ "no_sync": [],
+ "connect_method": [
+ "notBlank"
+ ],
+ "updated": [
+ "notBlank"
+ ],
+ "deleted": [],
+ "lazy_blocked": [],
+ "service_specific_id": [],
+ "subscriber_root": [],
+ "subscriber_user": [],
+ "enacted": [],
+ "kind": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "subscriber_network": [],
+ "provider_service": [
+ "notBlank"
+ ]
+ },
+ "id": 7,
+ "created": "2016-06-20T21:36:36.556180Z",
+ "updated": "2016-06-20T21:36:37.277167Z",
+ "enacted": "2016-06-20T21:43:30.075930Z",
+ "policed": null,
+ "backend_register": "{\"next_run\": 0, \"last_success\": 1466459040.216983, \"exponent\": 0}",
+ "backend_status": "1 - OK",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "kind": "vCPE",
+ "provider_service": 6,
+ "subscriber_service": null,
+ "subscriber_tenant": 6,
+ "subscriber_user": null,
+ "subscriber_root": null,
+ "subscriber_network": null,
+ "service_specific_id": null,
+ "service_specific_attribute": "{\"instance_id\": 1, \"creator_id\": 1, \"last_ansible_hash\": \"30d35de441b1e87e7e6a4fc79834ac56\"}",
+ "connect_method": "na"
+ },
+ {
+ "humanReadableName": "vROUTER-tenant-9",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_policy": [],
+ "subscriber_service": [],
+ "subscriber_tenant": [],
+ "no_sync": [],
+ "connect_method": [
+ "notBlank"
+ ],
+ "updated": [
+ "notBlank"
+ ],
+ "deleted": [],
+ "lazy_blocked": [],
+ "service_specific_id": [],
+ "subscriber_root": [],
+ "subscriber_user": [],
+ "enacted": [],
+ "kind": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "subscriber_network": [],
+ "provider_service": [
+ "notBlank"
+ ]
+ },
+ "id": 9,
+ "created": "2016-06-20T21:36:36.677067Z",
+ "updated": "2016-06-20T21:36:36.677678Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{\"next_run\": 1466494205.83568, \"last_failure\": 1466465405.835683, \"last_success\": 1466458621.14023, \"exponent\": 209, \"failures\": 209}",
+ "backend_status": "2 - Exception('Expecting object: line 1 column 1 (char 0) // Socket error: [Errno 111] Connection refused to http://onos-fabric:8181/onos/v1/network/configuration/hosts',)",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "kind": "vROUTER",
+ "provider_service": 5,
+ "subscriber_service": null,
+ "subscriber_tenant": 7,
+ "subscriber_user": null,
+ "subscriber_root": null,
+ "subscriber_network": null,
+ "service_specific_id": null,
+ "service_specific_attribute": "{\"public_ip\": \"10.168.0.3\", \"address_pool_id\": 2, \"public_mac\": \"02:42:0a:a8:00:03\"}",
+ "connect_method": "na"
+ },
+ {
+ "humanReadableName": "vROUTER-tenant-8",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_policy": [],
+ "subscriber_service": [],
+ "subscriber_tenant": [],
+ "no_sync": [],
+ "connect_method": [
+ "notBlank"
+ ],
+ "updated": [
+ "notBlank"
+ ],
+ "deleted": [],
+ "lazy_blocked": [],
+ "service_specific_id": [],
+ "subscriber_root": [],
+ "subscriber_user": [],
+ "enacted": [],
+ "kind": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "subscriber_network": [],
+ "provider_service": [
+ "notBlank"
+ ]
+ },
+ "id": 8,
+ "created": "2016-06-20T21:36:36.664628Z",
+ "updated": "2016-06-20T21:36:36.665255Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{\"next_run\": 1466494206.981866, \"last_failure\": 1466465406.981868, \"last_success\": 1466458619.671976, \"exponent\": 209, \"failures\": 209}",
+ "backend_status": "2 - Exception('Expecting object: line 1 column 1 (char 0) // Socket error: [Errno 111] Connection refused to http://onos-fabric:8181/onos/v1/network/configuration/hosts',)",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "kind": "vROUTER",
+ "provider_service": 5,
+ "subscriber_service": 6,
+ "subscriber_tenant": null,
+ "subscriber_user": null,
+ "subscriber_root": null,
+ "subscriber_network": null,
+ "service_specific_id": null,
+ "service_specific_attribute": "{\"public_ip\": \"10.168.0.2\", \"tenant_for_instance_id\": 1, \"address_pool_id\": 2, \"public_mac\": \"02:42:0a:a8:00:02\"}",
+ "connect_method": "na"
+ },
+ {
+ "humanReadableName": "onos-tenant-1",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_policy": [],
+ "subscriber_service": [],
+ "subscriber_tenant": [],
+ "no_sync": [],
+ "connect_method": [
+ "notBlank"
+ ],
+ "updated": [
+ "notBlank"
+ ],
+ "deleted": [],
+ "lazy_blocked": [],
+ "service_specific_id": [],
+ "subscriber_root": [],
+ "subscriber_user": [],
+ "enacted": [],
+ "kind": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "subscriber_network": [],
+ "provider_service": [
+ "notBlank"
+ ]
+ },
+ "id": 1,
+ "created": "2016-06-20T21:35:52.080746Z",
+ "updated": "2016-06-20T21:37:46.517157Z",
+ "enacted": "2016-06-20T21:37:55.377495Z",
+ "policed": null,
+ "backend_register": "{\"next_run\": 0, \"last_success\": 1466458677.529692, \"exponent\": 0}",
+ "backend_status": "1 - OK",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "kind": "onos",
+ "provider_service": 1,
+ "subscriber_service": 2,
+ "subscriber_tenant": null,
+ "subscriber_user": null,
+ "subscriber_root": null,
+ "subscriber_network": null,
+ "service_specific_id": null,
+ "service_specific_attribute": "{\"creator_id\": 1, \"dependencies\": \"org.onosproject.drivers, org.onosproject.drivers.ovsdb, org.onosproject.openflow-base, org.onosproject.ovsdb-base, org.onosproject.dhcp, org.onosproject.cordvtn, org.onosproject.olt, org.onosproject.igmp, org.onosproject.cordmcast\", \"name\": \"VTN_ONOS_app\"}",
+ "connect_method": "na"
+ },
+ {
+ "humanReadableName": "onos-tenant-5",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_policy": [],
+ "subscriber_service": [],
+ "subscriber_tenant": [],
+ "no_sync": [],
+ "connect_method": [
+ "notBlank"
+ ],
+ "updated": [
+ "notBlank"
+ ],
+ "deleted": [],
+ "lazy_blocked": [],
+ "service_specific_id": [],
+ "subscriber_root": [],
+ "subscriber_user": [],
+ "enacted": [],
+ "kind": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "subscriber_network": [],
+ "provider_service": [
+ "notBlank"
+ ]
+ },
+ "id": 5,
+ "created": "2016-06-20T21:36:36.499094Z",
+ "updated": "2016-06-20T21:36:36.498928Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{\"next_run\": 1466494235.874574, \"failures\": 732, \"last_success\": 1466458599.686363, \"exponent\": 732, \"last_failure\": 1466465435.874577}",
+ "backend_status": "2 - Exception('Ansible playbook failed. // Status code was not [200] // Status code was not [200]',)",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "kind": "onos",
+ "provider_service": 1,
+ "subscriber_service": 7,
+ "subscriber_tenant": null,
+ "subscriber_user": null,
+ "subscriber_root": null,
+ "subscriber_network": null,
+ "service_specific_id": null,
+ "service_specific_attribute": "{\"creator_id\": 1, \"dependencies\": \"org.onosproject.openflow-base, org.onosproject.olt, org.ciena.onos.ext_notifier, org.ciena.onos.volt_event_publisher\", \"name\": \"vOLT_ONOS_app\", \"install_dependencies\": \"onos-ext-notifier-1.0-SNAPSHOT.oar, onos-ext-volt-event-publisher-1.0-SNAPSHOT.oar\"}",
+ "connect_method": "na"
+ },
+ {
+ "humanReadableName": "onos-tenant-10",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_policy": [],
+ "subscriber_service": [],
+ "subscriber_tenant": [],
+ "no_sync": [],
+ "connect_method": [
+ "notBlank"
+ ],
+ "updated": [
+ "notBlank"
+ ],
+ "deleted": [],
+ "lazy_blocked": [],
+ "service_specific_id": [],
+ "subscriber_root": [],
+ "subscriber_user": [],
+ "enacted": [],
+ "kind": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "subscriber_network": [],
+ "provider_service": [
+ "notBlank"
+ ]
+ },
+ "id": 10,
+ "created": "2016-06-20T21:36:37.094935Z",
+ "updated": "2016-06-20T21:36:37.094764Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{\"next_run\": 1466494237.018397, \"failures\": 732, \"last_success\": 1466458602.833531, \"exponent\": 732, \"last_failure\": 1466465437.0184}",
+ "backend_status": "2 - Exception('Ansible playbook failed. // Socket error: [Errno 111] Connection refused to http://onos-fabric:8181/onos/v1/applications/org.onosproject.vrouter/active',)",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "kind": "onos",
+ "provider_service": 4,
+ "subscriber_service": 5,
+ "subscriber_tenant": null,
+ "subscriber_user": null,
+ "subscriber_root": null,
+ "subscriber_network": null,
+ "service_specific_id": null,
+ "service_specific_attribute": "{\"creator_id\": 1, \"dependencies\": \"org.onosproject.vrouter\", \"name\": \"vRouter_ONOS_app\"}",
+ "connect_method": "na"
+ },
+ {
+ "humanReadableName": "onos-tenant-2",
+ "validators": {
+ "service_specific_attribute": [],
+ "policed": [],
+ "backend_register": [
+ "notBlank"
+ ],
+ "backend_status": [
+ "notBlank"
+ ],
+ "id": [],
+ "no_policy": [],
+ "subscriber_service": [],
+ "subscriber_tenant": [],
+ "no_sync": [],
+ "connect_method": [
+ "notBlank"
+ ],
+ "updated": [
+ "notBlank"
+ ],
+ "deleted": [],
+ "lazy_blocked": [],
+ "service_specific_id": [],
+ "subscriber_root": [],
+ "subscriber_user": [],
+ "enacted": [],
+ "kind": [
+ "notBlank"
+ ],
+ "created": [],
+ "write_protect": [],
+ "subscriber_network": [],
+ "provider_service": [
+ "notBlank"
+ ]
+ },
+ "id": 2,
+ "created": "2016-06-20T21:35:56.835440Z",
+ "updated": "2016-06-20T21:35:56.835274Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{\"next_run\": 1466494229.282132, \"failures\": 736, \"last_success\": 1466458566.347982, \"exponent\": 736, \"last_failure\": 1466465429.282135}",
+ "backend_status": "2 - Exception('Ansible playbook failed. // Socket error: [Errno 111] Connection refused to http://onos-fabric:8181/onos/v1/applications/org.onosproject.lldpprovider/active // Socket error: [Errno 111] Connection refused to http://onos-fabric:8181/onos/v1/applications/org.onosproject.hostprovider/active // Socket error: [Errno 111] Connection refused to http://onos-fabric:8181/onos/v1/applications/org.onosproject.openflow-base/active // Socket error: [Errno 111] Connection refused to http://onos-fabric:8181/onos/v1/applications/org.onosproject.openflow/active // Socket error: [Errno 111] Connection refused to http://onos-fabric:8181/onos/v1/applications/org.onosproject.drivers/active // Socket error: [Errno 111] Connection refused to http://onos-fabric:8181/onos/v1/applications/org.onosproject.segmentrouting/active',)",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "no_policy": false,
+ "kind": "onos",
+ "provider_service": 4,
+ "subscriber_service": 3,
+ "subscriber_tenant": null,
+ "subscriber_user": null,
+ "subscriber_root": null,
+ "subscriber_network": null,
+ "service_specific_id": null,
+ "service_specific_attribute": "{\"creator_id\": 1, \"dependencies\": \"org.onosproject.lldpprovider, org.onosproject.hostprovider, org.onosproject.openflow-base, org.onosproject.openflow, org.onosproject.drivers, org.onosproject.segmentrouting\", \"name\": \"Fabric_ONOS_app\"}",
+ "connect_method": "na"
+ }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/mocks/diagnostic.conf.json b/views/ngXosViews/serviceGrid/mocks/diagnostic.conf.json
new file mode 100644
index 0000000..70c3337
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/mocks/diagnostic.conf.json
@@ -0,0 +1,52 @@
+{
+ "endpoints": [
+ {
+ "url": "images",
+ "base": "api/core/",
+ "methods": ["GET"],
+ "param": "id"
+ },
+ {
+ "url": "instances",
+ "base": "api/core/",
+ "methods": ["GET"],
+ "param": "id"
+ },
+ {
+ "url": "networks",
+ "base": "api/core/",
+ "methods": ["GET"],
+ "param": "id"
+ },
+ {
+ "url": "networktemplates",
+ "base": "api/core/",
+ "methods": ["GET"],
+ "param": "id"
+ },
+ {
+ "url": "services",
+ "base": "api/core/",
+ "methods": ["GET"],
+ "param": "id"
+ },
+ {
+ "url": "sites",
+ "base": "api/core/",
+ "methods": ["GET"],
+ "param": "id"
+ },
+ {
+ "url": "slices",
+ "base": "api/core/",
+ "methods": ["GET"],
+ "param": "id"
+ },
+ {
+ "url": "tenants",
+ "base": "api/core/",
+ "methods": ["GET"],
+ "param": "id"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/package.json b/views/ngXosViews/serviceGrid/package.json
index c33c615..130737b 100644
--- a/views/ngXosViews/serviceGrid/package.json
+++ b/views/ngXosViews/serviceGrid/package.json
@@ -9,7 +9,8 @@
"build": "gulp",
"test": "karma start",
"test:ci": "karma start --single-run",
- "lint": "eslint src/js/"
+ "lint": "eslint src/js/",
+ "server": "easy-mocker -c ./mocks/diagnostic.conf.json -d ./mocks/data"
},
"keywords": [
"XOS",
diff --git a/views/ngXosViews/serviceGrid/spec/sample.test.js b/views/ngXosViews/serviceGrid/spec/sample.test.js
deleted file mode 100644
index c026149..0000000
--- a/views/ngXosViews/serviceGrid/spec/sample.test.js
+++ /dev/null
@@ -1,37 +0,0 @@
-'use strict';
-
-describe('The User List', () => {
-
- var scope, element, isolatedScope, httpBackend;
-
- beforeEach(module('xos.serviceGrid'));
- beforeEach(module('templates'));
-
- beforeEach(inject(function($httpBackend, $compile, $rootScope){
-
- httpBackend = $httpBackend;
- // Setting up mock request
- $httpBackend.expectGET('/api/core/users/?no_hyperlinks=1').respond([
- {
- email: 'teo@onlab.us',
- firstname: 'Matteo',
- lastname: 'Scandolo'
- }
- ]);
-
- scope = $rootScope.$new();
- element = angular.element('<users-list></users-list>');
- $compile(element)(scope);
- scope.$digest();
- isolatedScope = element.isolateScope().vm;
- }));
-
- xit('should load 1 users', () => {
- httpBackend.flush();
- expect(isolatedScope.users.length).toBe(1);
- expect(isolatedScope.users[0].email).toEqual('teo@onlab.us');
- expect(isolatedScope.users[0].firstname).toEqual('Matteo');
- expect(isolatedScope.users[0].lastname).toEqual('Scandolo');
- });
-
-});
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/spec/services_encoder.test.js b/views/ngXosViews/serviceGrid/spec/services_encoder.test.js
new file mode 100644
index 0000000..3107b7f
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/spec/services_encoder.test.js
@@ -0,0 +1,223 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 6/22/16.
+ */
+
+(function () {
+ 'use strict';
+ describe('The Services Encoder Service', () => {
+
+ var service, rootScope, ArchiveManagerSpy, toscaBase;
+
+ const toscaBaseDefault = {
+ topology_template: {
+ node_templates: {}
+ }
+ };
+
+ beforeEach(module('xos.serviceGrid'));
+ beforeEach(module('templates'));
+
+ beforeEach(inject(($rootScope, ArchiveManager, ServiceEncoder) => {
+ rootScope = $rootScope;
+ toscaBase = angular.copy(toscaBaseDefault);
+
+ ArchiveManagerSpy = ArchiveManager;
+ spyOn(ArchiveManagerSpy, 'createArchive');
+ spyOn(ArchiveManagerSpy, 'addFile');
+ service = ServiceEncoder;
+ }));
+
+ describe('the formatServiceProperties method', () => {
+
+ it('should return only the existing properties', (done) => {
+ service.formatServiceProperties({name: 'test', kind: 'vCPE'}, toscaBase)
+ .then(res => {
+ expect(res).toEqual({
+ topology_template:{
+ node_templates: {
+ 'service#test': {
+ type: 'tosca.nodes.VSGService',
+ properties: {kind: 'vCPE'}
+ }
+ }
+ }
+ });
+ done();
+ });
+ rootScope.$apply();
+ });
+
+ it('should return all properties', (done) => {
+ service.formatServiceProperties({
+ name: 'test',
+ kind: 'vCPE',
+ view_url: 'view_url',
+ icon_url: 'icon_url',
+ private_key_fn: 'private_key_fn'
+ }, toscaBase)
+ .then(res => {
+ expect(res).toEqual({
+ topology_template:{
+ node_templates: {
+ 'service#test': {
+ type: 'tosca.nodes.VSGService',
+ properties: {
+ kind: 'vCPE',
+ view_url: 'view_url',
+ icon_url: 'icon_url',
+ private_key_fn: 'private_key_fn'
+ }
+ }
+ }
+ }
+ });
+ done();
+ });
+ rootScope.$apply();
+ });
+
+ describe('when a public key is provided', () => {
+ it('should add public_key and artifacts properties', (done) => {
+
+ let expected = {
+ topology_template:{
+ node_templates: {
+ 'service#test': {
+ type: 'tosca.nodes.VSGService',
+ properties: {
+ kind: 'vCPE',
+ public_key: '{ get_artifact: [ SELF, pubkey, LOCAL_FILE] }'
+ },
+ artifacts: {
+ pubkey: '/opt/xos/tosca/test/test_rsa.pub'
+ }
+ }
+ }
+ }
+ };
+
+ service.formatServiceProperties({
+ kind: 'vCPE',
+ public_key: 'pkey',
+ name: 'test'
+ }, toscaBase)
+ .then(res => {
+ expect(res).toEqual(expected);
+ done();
+ });
+ rootScope.$apply();
+ });
+
+ it('should add public_key file to the archive', (done) => {
+ service.formatServiceProperties({
+ kind: 'vCPE',
+ public_key: 'pkey',
+ name: 'test'
+ }, toscaBase)
+ .then(res => {
+ expect(ArchiveManagerSpy.addFile).toHaveBeenCalledWith('test_rsa.pub', 'pkey');
+ done();
+ });
+ rootScope.$apply();
+ });
+ });
+ });
+
+ describe('the getServiceRequirements method', () => {
+ let TenantSpy, ServiceSpy, tenantQueryPromise;
+ beforeEach(inject(function(Tenants, Services, $q){
+
+ tenantQueryPromise= $q.defer();
+
+ TenantSpy = Tenants;
+ spyOn(TenantSpy, 'query').and.callFake(function(){
+ return {$promise: tenantQueryPromise.promise};
+ });
+
+ ServiceSpy = Services;
+ spyOn(ServiceSpy, 'get').and.callFake(function(p){
+ let d = $q.defer();
+ d.resolve({name: `deps_${p.id}`});
+ return {$promise: d.promise};
+ });
+ }));
+
+ it('should call the tenants service with correct params', () => {
+ service.getServiceRequirements({id: 1});
+ expect(TenantSpy.query).toHaveBeenCalledWith({subscriber_service: 1});
+ });
+
+ it('should not add requirements if the current service has no dependency', (done) => {
+ service.getServiceRequirements({id: 1}, {})
+ .then(res => {
+ expect(res).toEqual({});
+ done();
+ });
+ tenantQueryPromise.resolve();
+ rootScope.$apply();
+ });
+
+ it('should return a list of required service', () => {
+ service.getServiceRequirements({id: 1, name: 'test'}, {topology_template: {node_templates: {'service#test': {}}}})
+ .then(res => {
+ expect(res.topology_template.node_templates['service#test'].requirements).toEqual([
+ {
+ deps_3_tenant: {
+ node: 'service#deps_3',
+ relationship: 'tosca.relationships.TenantOfService'
+ }
+ },
+ {
+ deps_4_tenant: {
+ node: 'service#deps_4',
+ relationship: 'tosca.relationships.TenantOfService'
+ }
+ }
+ ]);
+ });
+ tenantQueryPromise.resolve([
+ {
+ subscriber_service: 1,
+ provider_service: 3
+ },
+ {
+ subscriber_service: 1,
+ provider_service: 4
+ }
+ ]);
+ rootScope.$apply();
+ });
+
+ it('should return a list of unique required service', () => {
+ service.getServiceRequirements({id: 1, name: 'test'}, {topology_template: {node_templates: {'service#test': {}}}})
+ .then(res => {
+ expect(res.topology_template.node_templates['service#test'].requirements).toEqual([
+ {
+ deps_3_tenant: {
+ node: 'service#deps_3',
+ relationship: 'tosca.relationships.TenantOfService'
+ }
+ }
+ ]);
+ });
+ tenantQueryPromise.resolve([
+ {
+ subscriber_service: 1,
+ provider_service: 3
+ },
+ {
+ subscriber_service: 1,
+ provider_service: 3
+ }
+ ]);
+ rootScope.$apply();
+ });
+ });
+ });
+
+})();
+
diff --git a/views/ngXosViews/serviceGrid/spec/site_encoder.test.js b/views/ngXosViews/serviceGrid/spec/site_encoder.test.js
new file mode 100644
index 0000000..fdc6d50
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/spec/site_encoder.test.js
@@ -0,0 +1,62 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 6/22/16.
+ */
+
+(function () {
+ 'use strict';
+ describe('The Site Encoder service', () => {
+ let service, toscaBase, siteGetPromise, SiteSpy, rootScope;
+
+ const toscaBaseDefault = {
+ topology_template: {
+ node_templates: {}
+ }
+ };
+
+ const siteResponse = {
+ name: 'MySite'
+ };
+
+ const expected = [{
+ topology_template: {
+ node_templates: {
+ 'MySite': {
+ type: 'tosca.nodes.Site',
+ }
+ }
+ }
+ }, siteResponse];
+
+ beforeEach(module('xos.serviceGrid'));
+ beforeEach(module('templates'));
+
+ beforeEach(inject((SiteEncoder, Sites, $q, $rootScope) => {
+ toscaBase = angular.copy(toscaBaseDefault);
+ service = SiteEncoder;
+ rootScope = $rootScope;
+
+ siteGetPromise= $q.defer();
+ SiteSpy = Sites;
+ spyOn(SiteSpy, 'get').and.callFake(function(){
+ return {$promise: siteGetPromise.promise};
+ });
+ }));
+
+ describe('given a Site Id', () => {
+ it('should return the correct JSON structure', (done) => {
+ service.buildTosca({id: 1}, toscaBase)
+ .then(res => {
+ expect(res).toEqual(expected);
+ done();
+ });
+ siteGetPromise.resolve(siteResponse);
+ rootScope.$apply();
+ });
+ });
+ });
+})();
+
diff --git a/views/ngXosViews/serviceGrid/spec/slices_encoder.test.js b/views/ngXosViews/serviceGrid/spec/slices_encoder.test.js
new file mode 100644
index 0000000..f32bc9a
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/spec/slices_encoder.test.js
@@ -0,0 +1,103 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 6/22/16.
+ */
+
+(function () {
+ 'use strict';
+
+ describe('The Slices Encoder service', () => {
+
+ let service, toscaBase, sliceQueryPromise, SliceSpy, rootScope;
+
+ const toscaBaseDefault = {
+ topology_template: {
+ node_templates: {}
+ }
+ };
+
+ const slicesArray = [
+ {
+ name: 'Slice1',
+ description: 'Description1',
+ network: 'noauto'
+ },
+ {
+ name: 'Slice2',
+ description: 'Description2',
+ network: 'noauto'
+ }
+ ];
+
+ const expected = {
+ topology_template: {
+ node_templates: {
+ Slice1: {
+ description: 'Description1',
+ type: 'tosca.nodes.Slice',
+ properties: {
+ network: 'noauto'
+ },
+ requirements: [
+ {management: {node: 'management', relationship: 'tosca.relationships.ConnectsToNetwork'}},
+ {test_service: {node: 'service#test', relationship: 'tosca.relationships.MemberOfService'}}
+ ]
+ },
+ Slice2: {
+ description: 'Description2',
+ type: 'tosca.nodes.Slice',
+ properties: {
+ network: 'noauto'
+ },
+ requirements: [
+ {management: {node: 'management', relationship: 'tosca.relationships.ConnectsToNetwork'}},
+ {test_service: {node: 'service#test', relationship: 'tosca.relationships.MemberOfService'}}
+ ]
+ }
+ }
+ }
+ };
+
+ beforeEach(module('xos.serviceGrid'));
+ beforeEach(module('templates'));
+
+ beforeEach(inject((SlicesEncoder, Slices, $q, $rootScope) => {
+ toscaBase = angular.copy(toscaBaseDefault);
+ service = SlicesEncoder;
+ rootScope = $rootScope;
+
+ sliceQueryPromise= $q.defer();
+ SliceSpy = Slices;
+ spyOn(SliceSpy, 'query').and.callFake(function(){
+ return {$promise: sliceQueryPromise.promise};
+ });
+ }));
+
+ describe('given a Slices array ', () => {
+ it('should return the correct JSON structure', (done) => {
+ service.buildTosca(slicesArray, toscaBase, 'test')
+ .then(res => {
+ expect(res).toEqual(expected);
+ done();
+ });
+ rootScope.$apply();
+ });
+ });
+
+ describe('given a service', () => {
+ it('should return the JSON structure for all related slices', (done) => {
+ service.getServiceSlices({id : 1, name: 'test'}, toscaBase)
+ .then(res => {
+ expect(res).toEqual(expected);
+ done();
+ });
+ sliceQueryPromise.resolve(slicesArray);
+ rootScope.$apply();
+ });
+ });
+ });
+})();
+
diff --git a/views/ngXosViews/serviceGrid/spec/tosca_encoder.test.js b/views/ngXosViews/serviceGrid/spec/tosca_encoder.test.js
new file mode 100644
index 0000000..d968419
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/spec/tosca_encoder.test.js
@@ -0,0 +1,234 @@
+(function () {
+ 'use strict';
+ describe('The Tosca Encoder Service', () => {
+
+ var service, httpBackend, rootScope, ArchiveManagerSpy, toscaBase;
+
+ const serviceData = {
+ id: 1,
+ name: 'vsg',
+ kind: 'vCPE'
+ };
+
+ const toscaBaseDefault = {
+ topology_template: {
+ node_templates: {}
+ }
+ };
+
+ beforeEach(module('xos.serviceGrid'));
+ beforeEach(module('templates'));
+
+ beforeEach(inject(function($httpBackend, $rootScope, ToscaEncoder, ArchiveManager){
+
+ httpBackend = $httpBackend;
+ rootScope = $rootScope;
+ toscaBase = angular.copy(toscaBaseDefault);
+ service = ToscaEncoder;
+ ArchiveManagerSpy = ArchiveManager;
+ spyOn(ArchiveManagerSpy, 'createArchive');
+ spyOn(ArchiveManagerSpy, 'addFile');
+ spyOn(ArchiveManagerSpy, 'download');
+ }));
+
+ describe('the serviceToTosca method', () => {
+
+ const fakePropertiesDefault = {
+ tosca_definitions_version: 'tosca_simple_yaml_1_0',
+ description: 'Just enough Tosca to get the vSG slice running on the CORD POD',
+ imports: [
+ 'custom_types/xos.yaml'
+ ],
+ topology_template:{
+ node_templates: {
+ 'service#vsg': {
+ type: 'tosca.nodes.VSGService',
+ properties: {
+ view_url: 'viewUrl',
+ icon_url: 'iconUrl',
+ kind: 'vCPE'
+ }
+ }
+ }
+ }
+ };
+
+ const fakeRequirements = {
+ tosca_definitions_version: 'tosca_simple_yaml_1_0',
+ description: 'Just enough Tosca to get the vSG slice running on the CORD POD',
+ imports: [
+ 'custom_types/xos.yaml'
+ ],
+ topology_template:{
+ node_templates: {
+ 'service#vsg': {
+ type: 'tosca.nodes.VSGService',
+ properties: {
+ view_url: 'viewUrl',
+ icon_url: 'iconUrl',
+ kind: 'vCPE'
+ },
+ requirements: [
+ {
+ node: 'service#vrouter',
+ relationship: 'tosca.relationships.TenantOfService'
+ },
+ {
+ node: 'service#volt',
+ relationship: 'tosca.relationships.TenantOfService'
+ }
+ ]
+ }
+ }
+ }
+ };
+
+ const expectedWithoutRequirements = `tosca_definitions_version: tosca_simple_yaml_1_0
+description: Just enough Tosca to get the vSG slice running on the CORD POD
+imports:
+ - custom_types/xos.yaml
+topology_template:
+ node_templates:
+ service#vsg:
+ type: tosca.nodes.VSGService
+ properties:
+ view_url: viewUrl
+ icon_url: iconUrl
+ kind: vCPE
+`;
+
+ const expectedWithRequirements = `tosca_definitions_version: tosca_simple_yaml_1_0
+description: Just enough Tosca to get the vSG slice running on the CORD POD
+imports:
+ - custom_types/xos.yaml
+topology_template:
+ node_templates:
+ service#vsg:
+ type: tosca.nodes.VSGService
+ properties:
+ view_url: viewUrl
+ icon_url: iconUrl
+ kind: vCPE
+ requirements:
+ - node: service#vrouter
+ relationship: tosca.relationships.TenantOfService
+ - node: service#volt
+ relationship: tosca.relationships.TenantOfService
+`;
+
+ const expectedWithSlices = `tosca_definitions_version: tosca_simple_yaml_1_0
+description: Just enough Tosca to get the vSG slice running on the CORD POD
+imports:
+ - custom_types/xos.yaml
+topology_template:
+ node_templates:
+ service#vsg:
+ type: tosca.nodes.VSGService
+ properties:
+ view_url: viewUrl
+ icon_url: iconUrl
+ kind: vCPE
+ service_slice:
+ description: A service slice
+ type: tosca.nodes.Slice
+ properties:
+ network: noauto
+`;
+
+ let formatPromise, requirementPromise, slicesPromise, fakeProperties, serviceEncoderSpy, slicesEncoderSpy;
+
+ beforeEach(inject(($q, ServiceEncoder, SlicesEncoder) => {
+
+ serviceEncoderSpy = ServiceEncoder;
+ slicesEncoderSpy = SlicesEncoder;
+
+ // clone the base property for mock
+ fakeProperties = angular.copy(fakePropertiesDefault);
+
+ // create the promises
+ // this will be resolved in the single IT block,
+ // to allow different resolutions
+ formatPromise = $q.defer();
+ requirementPromise = $q.defer();
+ slicesPromise = $q.defer();
+
+ // mock functions and return promises
+ spyOn(serviceEncoderSpy, 'formatServiceProperties').and.callFake(function(){
+ return formatPromise.promise;
+ });
+ spyOn(serviceEncoderSpy, 'getServiceRequirements').and.callFake(function(){
+ return requirementPromise.promise;
+ });
+ spyOn(slicesEncoderSpy, 'getServiceSlices').and.callFake(function(){
+ return slicesPromise.promise;
+ });
+ }));
+
+ it('should create a new archive', () => {
+ service.serviceToTosca(serviceData);
+ expect(ArchiveManagerSpy.createArchive).toHaveBeenCalled();
+ });
+
+ it('should add the service file to the archive', (done) => {
+ service.serviceToTosca(serviceData)
+ .then(() => {
+ expect(ArchiveManagerSpy.addFile).toHaveBeenCalledWith('vsg_service.yaml', expectedWithoutRequirements);
+ expect(ArchiveManagerSpy.download).toHaveBeenCalledWith('vsg');
+ done();
+ });
+ formatPromise.resolve(fakeProperties);
+ requirementPromise.resolve(fakeProperties);
+ slicesPromise.resolve(fakeProperties);
+ rootScope.$apply();
+ });
+
+ // IS IT REALLY USEFULL TO TEST THE CONVERTION TO YAML?
+ xit('should create a tosca spec with no requirements', (done) => {
+ service.serviceToTosca(serviceData)
+ .then(res => {
+ expect(res).toEqual(expectedWithoutRequirements);
+ done();
+ });
+ formatPromise.resolve(fakeProperties);
+ requirementPromise.resolve(fakeProperties);
+ slicesPromise.resolve(fakeProperties);
+ rootScope.$apply();
+ });
+
+ xit('should create a tosca spec with requirements', (done) => {
+ service.serviceToTosca(serviceData)
+ .then(res => {
+ expect(res).toEqual(expectedWithRequirements);
+ done();
+ });
+ formatPromise.resolve(fakeProperties);
+ requirementPromise.resolve(fakeRequirements);
+ slicesPromise.resolve(fakeProperties);
+ rootScope.$apply();
+ });
+
+ xit('should create a tosca spec with additional slices', (done) => {
+
+ // this is dirty, we are changing an object and shouldn't be done in tests
+ angular.extend(
+ fakeProperties.topology_template.node_templates, {service_slice: {
+ description: 'A service slice',
+ type: 'tosca.nodes.Slice',
+ properties: {
+ network: 'noauto'
+ }
+ }});
+
+ service.serviceToTosca(serviceData)
+ .then(res => {
+ expect(res).toEqual(expectedWithSlices);
+ done();
+ });
+ formatPromise.resolve(fakeProperties);
+ requirementPromise.resolve(fakeProperties);
+ slicesPromise.resolve(fakeProperties);
+ rootScope.$apply();
+ });
+ });
+ });
+}());
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/src/index.html b/views/ngXosViews/serviceGrid/src/index.html
index d9e7fec..8f95e59 100644
--- a/views/ngXosViews/serviceGrid/src/index.html
+++ b/views/ngXosViews/serviceGrid/src/index.html
@@ -14,6 +14,9 @@
</div>
<!-- bower:js -->
+<script src="vendor/js-yaml/dist/js-yaml.js"></script>
+<script src="vendor/jszip/dist/jszip.js"></script>
+<script src="vendor/file-saver/FileSaver.js"></script>
<script src="vendor/jquery/dist/jquery.js"></script>
<script src="vendor/angular/angular.js"></script>
<script src="vendor/angular-mocks/angular-mocks.js"></script>
@@ -26,10 +29,19 @@
<script src="vendor/Chart.js/Chart.js"></script>
<script src="vendor/angular-chart.js/dist/angular-chart.js"></script>
<script src="vendor/d3/d3.js"></script>
+<script src="vendor/angular-recursion/angular-recursion.js"></script>
<!-- endbower -->
<!-- endjs -->
<!-- inject:js -->
<script src="/../../../xos/core/xoslib/static/js/vendor/ngXosHelpers.js"></script>
<script src="/.tmp/main.js"></script>
+<script src="/.tmp/tosca_encoder.service.js"></script>
+<script src="/.tmp/slices_encorder.service.js"></script>
+<script src="/.tmp/site_encode.service.js"></script>
+<script src="/.tmp/service_encorder.service.js"></script>
<script src="/.tmp/service-graph.js"></script>
+<script src="/.tmp/networks_encoder.service.js"></script>
+<script src="/.tmp/network_template_encoder.service.js"></script>
+<script src="/.tmp/image_encoder.service.js"></script>
+<script src="/.tmp/archive_manager.service.js"></script>
<!-- endinject -->
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/src/js/archive_manager.service.js b/views/ngXosViews/serviceGrid/src/js/archive_manager.service.js
new file mode 100644
index 0000000..92681ee
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/src/js/archive_manager.service.js
@@ -0,0 +1,39 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 6/22/16.
+ */
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc service
+ * @name xos.ArchiveManager.serviceGrid
+ **/
+
+ angular.module('xos.serviceGrid')
+ .service('ArchiveManager', function(){
+ this.createArchive = () => {
+ this.archive = new JSZip();
+ };
+
+ this.addFile = (fileName, content) => {
+ this.archive.file(fileName, content);
+ };
+
+ this.download = (name) => {
+ console.log(this.archive);
+ this.archive.generateAsync({type: 'blob'})
+ .then(function(content) {
+ saveAs(content, `${name}.zip`);
+ })
+ .catch(e => {
+ console.log(e);
+ });
+ };
+ });
+})();
+
diff --git a/views/ngXosViews/serviceGrid/src/js/image_encoder.service.js b/views/ngXosViews/serviceGrid/src/js/image_encoder.service.js
new file mode 100644
index 0000000..972023c
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/src/js/image_encoder.service.js
@@ -0,0 +1,40 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 6/22/16.
+ */
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc service
+ * @name xos.ImageEncoder.serviceGrid
+ **/
+
+ // TODO write tests
+ angular.module('xos.serviceGrid')
+ .service('ImageEncoder', function($q, Images){
+
+ this.buildTosca = (imageId, toscaSpec) => {
+ const d = $q.defer();
+
+ Images.get({id: imageId}).$promise
+ .then(image => {
+ const toscaObj = {};
+ toscaObj[`image#${image.name}`] = {
+ type: 'tosca.nodes.Image'
+ };
+ angular.extend(toscaSpec.topology_template.node_templates, toscaObj);
+ d.resolve([toscaSpec, image]);
+ })
+ .catch(d.reject);
+
+
+ return d.promise;
+ };
+ });
+})();
+
diff --git a/views/ngXosViews/serviceGrid/src/js/main.js b/views/ngXosViews/serviceGrid/src/js/main.js
index 88a0f95..fc75b2f 100644
--- a/views/ngXosViews/serviceGrid/src/js/main.js
+++ b/views/ngXosViews/serviceGrid/src/js/main.js
@@ -27,7 +27,7 @@
bindToController: true,
controllerAs: 'vm',
templateUrl: 'templates/service-grid.tpl.html',
- controller: function(Services, _){
+ controller: function(Services, ToscaEncoder, _){
this.tableConfig = {
columns: [
@@ -65,7 +65,21 @@
filter: 'field',
order: {
field: 'name'
- }
+ },
+ actions: [
+ {
+ label: 'export',
+ icon: 'export',
+ cb: service => {
+ this.tosca = '';
+ ToscaEncoder.serviceToTosca(service)
+ .then(tosca => {
+ this.showFeedback = true;
+ this.tosca = tosca;
+ });
+ }
+ }
+ ]
};
// retrieving user list
diff --git a/views/ngXosViews/serviceGrid/src/js/network_template_encoder.service.js b/views/ngXosViews/serviceGrid/src/js/network_template_encoder.service.js
new file mode 100644
index 0000000..1784d90
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/src/js/network_template_encoder.service.js
@@ -0,0 +1,40 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 6/22/16.
+ */
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc service
+ * @name xos.NetworkTemplateEncoder.serviceGrid
+ **/
+
+ // TODO write tests
+ angular.module('xos.serviceGrid')
+ .service('NetworkTemplateEncoder', function($q, Networkstemplates){
+
+ this.buildTosca = (templateId, toscaSpec) => {
+ const d = $q.defer();
+ Networkstemplates.get({id: templateId}).$promise
+ .then(template => {
+ const toscaObj = {};
+ toscaObj[`network_template#${template.name}`] = {
+ type: 'tosca.nodes.NetworkTemplate'
+ };
+ angular.extend(toscaSpec.topology_template.node_templates, toscaObj);
+ d.resolve([toscaSpec, template]);
+ })
+ .catch(e => {
+ d.reject(e);
+ });
+
+ return d.promise;
+ };
+ });
+})();
+
diff --git a/views/ngXosViews/serviceGrid/src/js/networks_encoder.service.js b/views/ngXosViews/serviceGrid/src/js/networks_encoder.service.js
new file mode 100644
index 0000000..1e6adee
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/src/js/networks_encoder.service.js
@@ -0,0 +1,132 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 6/22/16.
+ */
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc service
+ * @name xos.NetworkEncoder.serviceGrid
+ **/
+
+ // TODO write tests
+ angular.module('xos.serviceGrid')
+ .service('NetworkEncoder', function($q, Networks, NetworkTemplateEncoder){
+
+ this.buildTosca = (networks, toscaSpec) => {
+
+ const apiNetworks = angular.copy(networks);
+
+ // store here the promise that will build the dependency structure
+ let dependency = {
+ };
+
+ const d = $q.defer();
+
+ try {
+ networks = _.reduce(networks, (obj, n) => {
+ obj[`network#${n.name}`] = {
+ type: 'tosca.nodes.network.Network.XOS',
+ requirements: []
+ };
+
+ // for each network slice, add requirement
+ if(angular.isDefined(n.slices)) {
+ _.forEach(n.slices, s => {
+ let owner = {
+ owner: {
+ node: s.name,
+ relationship: 'tosca.relationships.MemberOfSlice'
+ }
+ };
+
+ let conn = {
+ connection: {
+ node: s.name,
+ relationship: 'tosca.relationships.ConnectsToSlice'
+ }
+ };
+ obj[`network#${n.name}`].requirements.push(owner, conn);
+ });
+
+ if(angular.isDefined(n.template)){
+ dependency[n.name] = NetworkTemplateEncoder.buildTosca(n.template, toscaSpec);
+ }
+ }
+
+ return obj;
+
+ }, {});
+
+ // if we have dependency wait for them
+ if(Object.keys(dependency).length > 0){
+ $q.all(dependency)
+ .then(deps => {
+ // NOTE how to make this readable??
+ if(deps){
+
+ // for each property in deps
+ for(let k of Object.keys(deps)){
+ let [tosca, template] = deps[k];
+ networks[`network#${k}`].requirements.push({
+ network_template: {
+ node: `network_template#${template.name}`,
+ relationship: 'tosca.relationships.UsesNetworkTemplate'
+ }
+ });
+ angular.extend(toscaSpec, tosca);
+ }
+ }
+ angular.extend(toscaSpec.topology_template.node_templates, networks);
+ d.resolve([toscaSpec, apiNetworks]);
+ })
+ .catch(e => {
+ throw new Error(e);
+ });
+ }
+ //else resolve directly
+ else {
+ angular.extend(toscaSpec.topology_template.node_templates, networks);
+ d.resolve([toscaSpec, apiNetworks]);
+ }
+ }
+ catch(e){
+ d.reject(e);
+ }
+
+ return d.promise;
+ };
+
+ this.getSliceNetworks = (slice, toscaSpec) => {
+ const d = $q.defer();
+ Networks.query({owner: slice.id}).$promise
+ .then((networks) => {
+ // check that all the network this slice own are listed in the slice
+ // does this make sense?
+ networks = _.filter(networks, n => {
+ return slice.networks.indexOf(n.id) !== -1;
+ });
+
+ // denormalize slice inside network
+ networks = networks.map(n => {
+ let idx = n.slices.indexOf(slice.id);
+ n.slices[idx] = slice;
+ return n;
+ });
+
+ this.buildTosca(networks, toscaSpec)
+ .then(d.resolve)
+ .catch(d.reject);
+
+ });
+
+ return d.promise;
+ }
+ });
+})();
+
diff --git a/views/ngXosViews/serviceGrid/src/js/service_encorder.service.js b/views/ngXosViews/serviceGrid/src/js/service_encorder.service.js
new file mode 100644
index 0000000..485d46a
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/src/js/service_encorder.service.js
@@ -0,0 +1,125 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 6/22/16.
+ */
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc service
+ * @name xos.toscaExporter.serviceGrid
+ **/
+
+ angular.module('xos.serviceGrid')
+ .service('ServiceEncoder', function($q, ArchiveManager, Tenants, Services){
+
+ const serviceTypes = {
+ fabric: 'tosca.nodes.FabricService',
+ onos: 'tosca.nodes.ONOSService',
+ vCPE: 'tosca.nodes.VSGService',
+ vOLT: 'tosca.nodes.VOLTService',
+ vROUTER: 'tosca.nodes.VRouterService',
+ VTN: 'tosca.nodes.VTNService',
+ vTR: 'tosca.nodes.Service'
+ };
+
+ this.formatServiceProperties = (service, toscaSpec) => {
+ const d = $q.defer();
+ const serviceName = `service#${service.name}`;
+ // create the structure to hold the service
+ toscaSpec.topology_template.node_templates[serviceName] = {};
+ toscaSpec.topology_template.node_templates[serviceName].type = serviceTypes[service.kind] || 'tosca.nodes.Service';
+
+ const res = {
+ properties: {
+ kind: service.kind
+ }
+ };
+
+ if(angular.isDefined(service.view_url)){
+ res.properties.view_url = service.view_url;
+ }
+
+ if(angular.isDefined(service.icon_url)){
+ res.properties.icon_url = service.icon_url;
+ }
+
+ if(angular.isDefined(service.private_key_fn)){
+ res.properties.private_key_fn = service.private_key_fn;
+ }
+
+ if(angular.isDefined(service.public_key)){
+ ArchiveManager.addFile(`${service.name}_rsa.pub`, service.public_key);
+ res.properties.public_key = '{ get_artifact: [ SELF, pubkey, LOCAL_FILE] }'
+ res['artifacts'] = {
+ pubkey: `/opt/xos/tosca/${service.name}/${service.name}_rsa.pub`
+ };
+ toscaSpec.topology_template.node_templates[serviceName].artifacts = res.artifacts;
+ }
+
+ toscaSpec.topology_template.node_templates[serviceName].properties = res.properties;
+ d.resolve(toscaSpec);
+ return d.promise;
+ };
+
+ this.getServiceRequirements = (service, toscaSpec) => {
+ const d = $q.defer();
+
+ Tenants.query({subscriber_service: service.id}).$promise
+ .then(tenants => {
+ const services = [];
+ // avoid multiple request for the same service
+ tenants = _.uniqBy(tenants, 'provider_service');
+
+ _.forEach(tenants, t => {
+ services.push(Services.get({id: t.provider_service}).$promise);
+ });
+
+ return $q.all(services)
+ })
+ .then((deps) => {
+ // Get the provider service and create an array of unique names
+ let requirements = _.reduce(deps, (list, d) => list.concat(d.name), []);
+
+ // create a object for requirements, later will parsed in Yaml
+ requirements = _.reduce(requirements, (list, r) => {
+ let name = `${r}_tenant`;
+ let obj = {};
+ obj[name] = {
+ node: `service#${r}`,
+ relationship: 'tosca.relationships.TenantOfService'
+ };
+ return list.concat(obj);
+ }, []);
+
+ if(requirements.length > 0){
+
+ // NOTE set a reference to the requirements in tosca
+ _.forEach(requirements, r => {
+ let reqName = r[Object.keys(r)[0]].node;
+ toscaSpec.topology_template.node_templates[reqName] = {
+ type: 'tosca.nodes.Service',
+ properties: {
+ 'no-create': true,
+ 'no-delete': true,
+ 'no-update': true
+ }
+ };
+ });
+
+ const serviceName = `service#${service.name}`;
+ toscaSpec.topology_template.node_templates[serviceName].requirements = requirements;
+ }
+
+ d.resolve(toscaSpec);
+ });
+
+ return d.promise;
+ };
+ });
+})();
+
diff --git a/views/ngXosViews/serviceGrid/src/js/site_encode.service.js b/views/ngXosViews/serviceGrid/src/js/site_encode.service.js
new file mode 100644
index 0000000..6bb1d99
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/src/js/site_encode.service.js
@@ -0,0 +1,39 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 6/22/16.
+ */
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc service
+ * @name xos.SiteEncoder.serviceGrid
+ **/
+
+ angular.module('xos.serviceGrid')
+ .service('SiteEncoder', function($q, Sites){
+
+ this.buildTosca = (siteId, toscaSpec) => {
+ const d = $q.defer();
+
+ Sites.get({id: siteId}).$promise
+ .then(site => {
+ const toscaObj = {};
+ toscaObj[`${site.name}`] = {
+ type: 'tosca.nodes.Site'
+ };
+ angular.extend(toscaSpec.topology_template.node_templates, toscaObj);
+ d.resolve([toscaSpec, site]);
+ })
+ .catch(d.reject);
+
+
+ return d.promise;
+ };
+ });
+})();
+
diff --git a/views/ngXosViews/serviceGrid/src/js/slices_encorder.service.js b/views/ngXosViews/serviceGrid/src/js/slices_encorder.service.js
new file mode 100644
index 0000000..f900d98
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/src/js/slices_encorder.service.js
@@ -0,0 +1,159 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 6/22/16.
+ */
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc service
+ * @name xos.SlicesEncoder.serviceGrid
+ **/
+
+ angular.module('xos.serviceGrid')
+ .service('SlicesEncoder', function($q, _, Slices, SiteEncoder, ImageEncoder, NetworkEncoder){
+
+ this.buildTosca = (slices, toscaSpec, serviceName) => {
+ // store here the promise that will build the dependency structure
+ let dependency = {};
+
+ const d = $q.defer();
+ slices = _.reduce(slices, (obj, s) => {
+ obj[s.name] = {
+ type: 'tosca.nodes.Slice',
+ properties: {
+ network: s.network
+ },
+ requirements: [
+ // by default slices are connected to management network
+ {
+ management: {
+ node: 'management',
+ relationship: 'tosca.relationships.ConnectsToNetwork'
+ }
+ },
+ ]
+ };
+
+ if(angular.isDefined(serviceName)){
+ let service = {};
+ service[`${serviceName}_service`] = {
+ node: `service#${serviceName}`,
+ relationship: 'tosca.relationships.MemberOfService'
+ };
+ obj[s.name].requirements.push(service);
+ }
+
+ if(angular.isDefined(s.description)){
+ obj[s.name].description = s.description;
+ }
+
+ if(angular.isDefined(s.site)){
+ dependency[`${s.name}#site`] = SiteEncoder.buildTosca(s.site, toscaSpec);
+ }
+ if(angular.isDefined(s.default_image)){
+ dependency[`${s.name}#image`] = ImageEncoder.buildTosca(s.default_image, toscaSpec);
+ }
+ if(angular.isDefined(s.networks) && s.networks.length > 0){
+ dependency[`${s.name}#management`] = NetworkEncoder.getSliceNetworks(s, toscaSpec);
+ }
+
+ return obj;
+ }, {});
+
+ // if we have dependency wait for them
+ if(Object.keys(dependency).length > 0){
+
+ let relationMap = {
+ site: 'tosca.relationships.MemberOfSite',
+ image: 'tosca.relationships.DefaultImage'
+ };
+
+ // NOTE create a reference to the management network
+ toscaSpec.topology_template.node_templates['management'] = {
+ type: 'tosca.nodes.network.Network.XOS',
+ properties: {
+ 'no-create': true,
+ 'no-delete': true,
+ 'no-update': true
+ }
+ };
+
+ $q.all(dependency)
+ .then(deps => {
+
+ for(let k of Object.keys(deps)){
+
+ // this is UGLY!!!
+ // we are passing the requirement type inside the object key
+ // in which the promise is stored.
+ // This let us build the requirements array
+ let [sliceName, requirementType] = k.split('#');
+
+ if(angular.isDefined(relationMap[requirementType])){
+
+ if(!slices[sliceName].requirements){
+ slices[sliceName].requirements = [];
+ }
+
+ let [tosca, resource] = deps[k];
+
+ let requirementObj = {};
+
+ let reqName;
+
+ // NOTE site have problem with prefixing
+ if(requirementType === 'site'){
+ reqName = resource.name;
+ }
+ else{
+ reqName = `${requirementType}#${resource.name}`;
+ }
+
+ requirementObj[requirementType] = {
+ node: reqName,
+ relationship: relationMap[requirementType]
+ };
+
+ slices[sliceName].requirements.push(requirementObj);
+
+ angular.extend(toscaSpec, tosca);
+ }
+
+ }
+ // here we add slices to tosca
+ angular.extend(toscaSpec.topology_template.node_templates, slices);
+ d.resolve(toscaSpec);
+ })
+ .catch(e => {
+ throw new Error(e);
+ });
+ }
+ //else resolve directly
+ else {
+ angular.extend(toscaSpec.topology_template.node_templates, slices);
+ d.resolve(toscaSpec);
+ }
+
+ return d.promise;
+ };
+
+ this.getServiceSlices = (service, toscaSpec) => {
+ const d = $q.defer();
+ Slices.query({service: service.id}).$promise
+ .then(slices => {
+ return this.buildTosca(slices, toscaSpec, service.name)
+ })
+ .then(slicesTosca => {
+ d.resolve(slicesTosca);
+ });
+
+ return d.promise;
+ };
+ });
+})();
+
diff --git a/views/ngXosViews/serviceGrid/src/js/tosca_encoder.service.js b/views/ngXosViews/serviceGrid/src/js/tosca_encoder.service.js
new file mode 100644
index 0000000..5798aca
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/src/js/tosca_encoder.service.js
@@ -0,0 +1,79 @@
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc service
+ * @name xos.toscaExporter.serviceGrid
+ **/
+
+ angular.module('xos.serviceGrid')
+ .service('ToscaEncoder', function($q, _, ArchiveManager, ServiceEncoder, SlicesEncoder){
+
+ let toscaSpec = {
+ tosca_definitions_version: 'tosca_simple_yaml_1_0',
+ description: '',
+ imports: [
+ 'custom_types/xos.yaml'
+ ],
+ topology_template:{
+ node_templates: {}
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name xos.serviceGrid.ToscaEncoder#$toYml
+ * @methodOf xos.serviceGrid.ToscaEncoder
+ * @description
+ * Convert a Json data structure to Yaml, use https://github.com/nodeca/js-yaml
+ * @param {Object} item A Json object to be converted
+ * @returns {string} The Yaml representation of the Json input
+ **/
+
+ this.toYml = (item) => {
+ return jsyaml.dump(item).replace(/'/g, '');
+ };
+
+ this.export = (service) => {
+ ArchiveManager.download(service.name);
+ const file = this.toYml(toscaSpec);
+ return file;
+ };
+
+ this.serviceToTosca = service => {
+
+ ArchiveManager.createArchive();
+ //clean
+ toscaSpec.topology_template.node_templates = {};
+
+ toscaSpec.description = `Just enough Tosca to get the ${service.humanReadableName} service up and running`;
+
+ const d = $q.defer();
+
+ // build service properties
+ ServiceEncoder.formatServiceProperties(service, toscaSpec)
+ .then(spec => {
+ return SlicesEncoder.getServiceSlices(service, spec);
+ })
+ // add required slices (and it will all the slice requirements)
+ .then((spec) => {
+ return ServiceEncoder.getServiceRequirements(service, spec);
+ })
+ // add required services (provider services)
+ .then((spec) => {
+ ArchiveManager.addFile(`${service.name}_service.yaml`, this.toYml(spec));
+
+ this.export(service);
+
+ d.resolve(this.toYml(spec));
+ })
+ .catch(e => {
+ d.reject(e);
+ });
+ return d.promise;
+
+ }
+
+ });
+
+}());
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/src/templates/service-grid.tpl.html b/views/ngXosViews/serviceGrid/src/templates/service-grid.tpl.html
index fa324b4..8e88e38 100644
--- a/views/ngXosViews/serviceGrid/src/templates/service-grid.tpl.html
+++ b/views/ngXosViews/serviceGrid/src/templates/service-grid.tpl.html
@@ -11,4 +11,16 @@
Tenancy Graph
</a> -->
</div>
-</div>
\ No newline at end of file
+</div>
+
+<div class="row">
+ <div class="col-xs-12">
+ <div class="alert alert-info" ng-show="vm.showFeedback">
+ Remember that you should copy any key artifact inside the container in <pre>/opt/xos/tosca</pre>!
+ </div>
+ </div>
+</div>
+
+<pre ng-show="vm.tosca">
+{{vm.tosca}}
+</pre>
\ No newline at end of file