--- /dev/null
+# -*- coding: utf-8 -*-
+##
+# Copyright 2018 University of Bristol - High Performance Networks Research
+# Group
+# All Rights Reserved.
+#
+# Contributors: Anderson Bravalheri, Dimitrios Gkounis, Abubakar Siddique
+# Muqaddas, Navdeep Uniyal, Reza Nejabati and Dimitra Simeonidou
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: <highperformance-networks@bristol.ac.uk>
+#
+# Neither the name of the University of Bristol nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# This work has been performed in the context of DCMS UK 5G Testbeds
+# & Trials Programme and in the framework of the Metro-Haul project -
+# funded by the European Commission under Grant number 761727 through the
+# Horizon 2020 and 5G-PPP programmes.
+##
+# pylint: disable=W0621
+
+from __future__ import unicode_literals
+
+import json
+from time import time
+from textwrap import wrap
+
+from ...tests.db_helpers import uuid, sha1
+
+NUM_WIMS = 3
+NUM_TENANTS = 2
+NUM_DATACENTERS = 2
+
+
+# In the following functions, the identifiers should be simple integers
+
+
+def wim(identifier=0):
+ return {'name': 'wim%d' % identifier,
+ 'uuid': uuid('wim%d' % identifier),
+ 'wim_url': 'localhost',
+ 'type': 'ietfl2vpn'}
+
+
+def tenant(identifier=0):
+ return {'name': 'tenant%d' % identifier,
+ 'uuid': uuid('tenant%d' % identifier)}
+
+
+def wim_account(wim, tenant):
+ return {'name': 'wim-account%d%d' % (tenant, wim),
+ 'uuid': uuid('wim-account%d%d' % (tenant, wim)),
+ 'user': 'user%d%d' % (tenant, wim),
+ 'password': 'password%d%d' % (tenant, wim),
+ 'wim_id': uuid('wim%d' % wim),
+ 'created': 'true'}
+
+
+def wim_tenant_association(wim, tenant):
+ return {'nfvo_tenant_id': uuid('tenant%d' % tenant),
+ 'wim_id': uuid('wim%d' % wim),
+ 'wim_account_id': uuid('wim-account%d%d' % (tenant, wim))}
+
+
+def wim_set(identifier=0, tenant=0):
+ """Records necessary to create a WIM and connect it to a tenant"""
+ return [
+ {'wims': [wim(identifier)]},
+ {'wim_accounts': [wim_account(identifier, tenant)]},
+ {'wim_nfvo_tenants': [wim_tenant_association(identifier, tenant)]}
+ ]
+
+
+def _datacenter_to_switch_port(dc_id, port=None):
+ digits = 16
+ switch = ':'.join(wrap(('%0' + str(digits) + 'x') % int(dc_id), 2))
+ return (switch, str((port or int(dc_id)) + 1))
+
+
+def datacenter(identifier, external_ports_config=False):
+ config = '' if not external_ports_config else json.dumps({
+ 'external_connections': [
+ {'condition': {
+ 'provider:physical_network': 'provider',
+ 'encapsulation_type': 'vlan'},
+ 'vim_external_port':
+ dict(zip(('switch', 'port'),
+ _datacenter_to_switch_port(identifier)))}
+ ]})
+
+ return {'uuid': uuid('dc%d' % identifier),
+ 'name': 'dc%d' % identifier,
+ 'type': 'openvim',
+ 'vim_url': 'localhost',
+ 'config': config}
+
+
+def datacenter_account(datacenter, tenant):
+ return {'name': 'dc-account%d%d' % (tenant, datacenter),
+ 'uuid': uuid('dc-account%d%d' % (tenant, datacenter)),
+ 'datacenter_id': uuid('dc%d' % datacenter),
+ 'created': 'true'}
+
+
+def datacenter_tenant_association(datacenter, tenant):
+ return {'nfvo_tenant_id': uuid('tenant%d' % tenant),
+ 'datacenter_id': uuid('dc%d' % datacenter),
+ 'datacenter_tenant_id': uuid('dc-account%d%d' % (tenant, datacenter))}
+
+
+def datacenter_set(identifier=0, tenant=0):
+ """Records necessary to create a datacenter and connect it to a tenant"""
+ return [
+ {'datacenters': [datacenter(identifier)]},
+ {'datacenter_tenants': [datacenter_account(identifier, tenant)]},
+ {'tenants_datacenters': [
+ datacenter_tenant_association(identifier, tenant)
+ ]}
+ ]
+
+
+def wim_port_mapping(wim, datacenter,
+ pop_dpid='AA:AA:AA:AA:AA:AA:AA:AA', pop_port=None,
+ wan_dpid='BB:BB:BB:BB:BB:BB:BB:BB', wan_port=None):
+ mapping_info = {'mapping_type': 'dpid-port',
+ 'wan_switch_dpid': wan_dpid,
+ 'wan_switch_port': (str(wan_port) if wan_port else
+ str(int(datacenter) + int(wim) + 1))}
+ id_ = 'dpid-port|' + sha1(json.dumps(mapping_info, sort_keys=True))
+
+ return {'wim_id': uuid('wim%d' % wim),
+ 'datacenter_id': uuid('dc%d' % datacenter),
+ 'device_id': pop_dpid,
+ 'device_interface_id': (str(pop_port) if pop_port else
+ str(int(datacenter) + int(wim) + 1)),
+ # ^ Datacenter router have one port managed by each WIM
+ 'service_endpoint_id': id_,
+ # ^ WIM managed router have one port connected to each DC
+ 'service_mapping_info': json.dumps(mapping_info)}
+
+
+def processed_port_mapping(wim, datacenter,
+ num_pairs=1,
+ pop_dpid='AA:AA:AA:AA:AA:AA:AA:AA',
+ wan_dpid='BB:BB:BB:BB:BB:BB:BB:BB'):
+ """Emulate the response of the Persistence class, where the records in the
+ data base are grouped by wim and datacenter
+ """
+ return {
+ 'wim_id': uuid('wim%d' % wim),
+ 'datacenter_id': uuid('dc%d' % datacenter),
+ 'pop_wan_mappings': [
+ {'device_id': pop_dpid,
+ 'device_interface_id': wim + 1 + i,
+ 'service_endpoint_id':
+ sha1('dpid-port|%s|%d' % (wan_dpid, datacenter + 1 + i)),
+ 'service_mapping_info': {
+ 'mapping_type': 'dpid-port',
+ 'wan_switch_dpid': wan_dpid,
+ 'wan_switch_port': datacenter + 1 + i}}
+ for i in range(num_pairs)
+ ]
+ }
+
+
+def consistent_set(num_wims=NUM_WIMS, num_tenants=NUM_TENANTS,
+ num_datacenters=NUM_DATACENTERS,
+ external_ports_config=False):
+ return [
+ {'nfvo_tenants': [tenant(i) for i in range(num_tenants)]},
+ {'wims': [wim(j) for j in range(num_wims)]},
+ {'wim_accounts': [
+ wim_account(j, i)
+ for i in range(num_tenants)
+ for j in range(num_wims)
+ ]},
+ {'wim_nfvo_tenants': [
+ wim_tenant_association(j, i)
+ for i in range(num_tenants)
+ for j in range(num_wims)
+ ]},
+ {'datacenters': [
+ datacenter(k, external_ports_config)
+ for k in range(num_datacenters)
+ ]},
+ {'datacenter_tenants': [
+ datacenter_account(k, i)
+ for i in range(num_tenants)
+ for k in range(num_datacenters)
+ ]},
+ {'tenants_datacenters': [
+ datacenter_tenant_association(k, i)
+ for i in range(num_tenants)
+ for k in range(num_datacenters)
+ ]},
+ {'wim_port_mappings': [
+ (wim_port_mapping(j, k, *_datacenter_to_switch_port(k))
+ if external_ports_config else wim_port_mapping(j, k))
+ for j in range(num_wims)
+ for k in range(num_datacenters)
+ ]},
+ ]
+
+
+def instance_nets(num_datacenters=2, num_links=2, status='BUILD'):
+ """Example of multi-site deploy with N datacenters and M WAN links between
+ them (e.g M = 2 -> back and forth)
+ """
+ return [
+ {'uuid': uuid('net%d%d' % (k, li)),
+ 'datacenter_id': uuid('dc%d' % k),
+ 'datacenter_tenant_id': uuid('dc-account0%d' % k),
+ 'instance_scenario_id': uuid('nsr0'),
+ # ^ instance_scenario_id == NS Record id
+ 'sce_net_id': uuid('vld%d' % li),
+ # ^ scenario net id == VLD id
+ 'status': status,
+ 'vim_net_id': None,
+ 'created': True}
+ for k in range(num_datacenters)
+ for li in range(num_links)
+ ]
+
+
+def wim_actions(action='CREATE', status='SCHEDULED',
+ action_id=None, instance=0,
+ wim=0, tenant=0, num_links=1):
+ """Create a list of actions for the WIM,
+
+ Arguments:
+ action: type of action (CREATE) by default
+ wim: WIM fixture index to create actions for
+ tenant: tenant fixture index to create actions for
+ num_links: number of WAN links to be established by each WIM
+ """
+
+ action_id = action_id or 'ACTION-{}'.format(time())
+
+ return [
+ {
+ 'action': action,
+ 'wim_internal_id': uuid('-wim-net%d%d%d' % (wim, instance, link)),
+ 'wim_account_id': uuid('wim-account%d%d' % (tenant, wim)),
+ 'instance_action_id': action_id,
+ 'item': 'instance_wim_nets',
+ 'item_id': uuid('wim-net%d%d%d' % (wim, instance, link)),
+ 'status': status,
+ 'task_index': link,
+ 'created_at': time(),
+ 'modified_at': time(),
+ 'extra': None
+ }
+ for link in range(num_links)
+ ]
+
+
+def instance_action(tenant=0, instance=0, action_id=None,
+ num_tasks=1, num_done=0, num_failed=0):
+ action_id = action_id or 'ACTION-{}'.format(time())
+
+ return {
+ 'uuid': action_id,
+ 'tenant_id': uuid('tenant%d' % tenant),
+ 'instance_id': uuid('nsr%d' % instance),
+ 'number_tasks': num_tasks,
+ 'number_done': num_done,
+ 'number_failed': num_failed,
+ }
+
+
+def instance_wim_nets(instance=0, wim=0, num_links=1,
+ status='SCHEDULED_CREATION'):
+ """Example of multi-site deploy with N wims and M WAN links between
+ them (e.g M = 2 -> back and forth)
+ VIM nets
+ """
+ return [
+ {'uuid': uuid('wim-net%d%d%d' % (wim, instance, li)),
+ 'wim_id': uuid('wim%d' % wim),
+ 'wim_account_id': uuid('wim-account%d' % wim),
+ 'wim_internal_id': uuid('-net%d%d' % (wim, li)),
+ 'instance_scenario_id': uuid('nsr%d' % instance),
+ # ^ instance_scenario_id == NS Record id
+ 'sce_net_id': uuid('vld%d' % li),
+ # ^ scenario net id == VLD id
+ 'status': status,
+ 'created': False}
+ for li in range(num_links)
+ ]
+
+
+def instance_vm(instance=0, vim_info=None):
+ vim_info = {'OS-EXT-SRV-ATTR:hypervisor_hostname': 'host%d' % instance}
+ return {
+ 'uuid': uuid('vm%d' % instance),
+ 'instance_vnf_id': uuid('vnf%d' % instance),
+ 'vm_id': uuid('vm%d' % instance),
+ 'vim_vm_id': uuid('vm%d' % instance),
+ 'status': 'ACTIVE',
+ 'vim_info': vim_info,
+ }
+
+
+def instance_interface(instance=0, interface=0, datacenter=0, link=0):
+ return {
+ 'uuid': uuid('interface%d%d' % (instance, interface)),
+ 'instance_vm_id': uuid('vm%d' % instance),
+ 'instance_net_id': uuid('net%d%d' % (datacenter, link)),
+ 'interface_id': uuid('iface%d' % interface),
+ 'type': 'external',
+ 'vlan': 3
+ }