--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
+
+from emuvim.api.openstack.openstack_api_endpoint import OpenstackApiEndpoint
+from emuvim.api.osm.kafka import Kafka
+from emuvim.api.osm.lcm import LCM
+from emuvim.api.osm.mongo import Mongo
+from emuvim.api.osm.mysql import Mysql
+from emuvim.api.osm.nbi import NBI
+from emuvim.api.osm.ro import RO
+from emuvim.api.osm.zookeeper import Zookeeper
+from emuvim.dcemulator.net import DCNetwork
+
+
+from mininet.log import setLogLevel
+setLogLevel('debug')
+
+net = DCNetwork(monitor=False, enable_learning=True)
+api = None
+try:
+ dc1 = net.addDatacenter("dc1")
+ api = OpenstackApiEndpoint("0.0.0.0", 6001)
+ api.connect_datacenter(dc1)
+ api.connect_dc_network(net)
+
+ s1 = net.addSwitch('s1')
+
+ zookeeper_ip = '10.0.0.96'
+ kafka_ip = '10.0.0.97'
+ mongo_ip = '10.0.0.98'
+ nbi_ip = '10.0.0.99'
+ ro_db_ip = '10.0.0.100'
+ ro_ip = '10.0.0.101'
+ lcm_ip = '10.0.0.102'
+
+ d1 = net.addDocker('d1', dimage='ubuntu:trusty')
+
+ VERSION = 'releasefive-daily'
+
+ zookeeper = Zookeeper(net, zookeeper_ip)
+ kafka = Kafka(net, kafka_ip, zookeeper_ip)
+ mongo = Mongo(net, mongo_ip)
+ nbi = NBI(net, nbi_ip, mongo_ip, kafka_ip)
+ ro_db = Mysql(net, ro_db_ip)
+ ro = RO(net, ro_ip, ro_db_ip, version=VERSION)
+ lcm = LCM(net, lcm_ip, ro_ip, mongo_ip, kafka_ip)
+
+ net.addLink(d1, s1)
+ net.addLink(zookeeper.instance, s1)
+ net.addLink(kafka.instance, s1)
+ net.addLink(mongo.instance, s1)
+ net.addLink(nbi.instance, s1)
+ net.addLink(ro_db.instance, s1)
+ net.addLink(ro.instance, s1)
+ net.addLink(lcm.instance, s1)
+
+ net.start()
+ api.start()
+
+ zookeeper.start()
+ kafka.start()
+ mongo.start()
+ nbi.start()
+ ro_db.start()
+ ro.start()
+ lcm.start()
+ vim_id = nbi.register_emulated_api('emu-vim1', api)
+
+ net.ping([d1, zookeeper.instance])
+ net.ping([d1, kafka.instance])
+ net.ping([d1, mongo.instance])
+ net.ping([d1, nbi.instance])
+ net.ping([d1, ro.instance])
+ net.ping([d1, ro_db.instance])
+ net.ping([d1, lcm.instance])
+
+ nbi.onboard_vnfd('vnfs/ping_vnf')
+ nbi.onboard_vnfd('vnfs/pong_vnf')
+ nsd_id = nbi.onboard_nsd('services/pingpong_ns')
+ ns_id = nbi.ns_create('pingpong-test', nsd_id=nsd_id, vim_id=vim_id)
+
+ nbi.ns_wait_until_all_in_status('running')
+ nbi.ns_delete(ns_id)
+ nbi.ns_wait_until_all_in_status('terminated')
+finally:
+ net.stop()
+ api.stop()
--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
+
+
+from emuvim.api.openstack.openstack_api_endpoint import OpenstackApiEndpoint
+from emuvim.api.osm.osm import OSM
+from emuvim.dcemulator.net import DCNetwork
+
+net = DCNetwork(monitor=False, enable_learning=True)
+dc1 = net.addDatacenter("dc1")
+api = OpenstackApiEndpoint("0.0.0.0", 6001)
+api.connect_datacenter(dc1)
+api.connect_dc_network(net)
+
+try:
+ s1 = net.addSwitch('s1')
+ s2 = net.addSwitch('s2')
+ osm1 = OSM(net, s1, name='1')
+ osm2 = OSM(net, s2, name='2')
+
+ net.start()
+ api.start()
+ osm1.start()
+ print('osm1 up!')
+ osm2.start()
+ print('osm2 up!')
+
+ vim_id1 = osm1.register_emulated_api('vim', api)
+ osm1.onboard_vnfd('vnfs/ping_vnf')
+ osm1.onboard_vnfd('vnfs/pong_vnf')
+ nsd_id1 = osm1.onboard_nsd('services/pingpong_ns')
+ ns_id1 = osm1.ns_create('pingpong-test1', nsd_id1, vim_id1)
+
+ vim_id2 = osm2.register_emulated_api('vim', api)
+ osm2.onboard_vnfd('vnfs/ping_vnf')
+ osm2.onboard_vnfd('vnfs/pong_vnf')
+ nsd_id2 = osm2.onboard_nsd('services/pingpong_ns')
+ ns_id2 = osm2.ns_create('pingpong-test2', nsd_id2, vim_id2)
+
+ osm1.ns_wait_until_all_in_status('running')
+ osm2.ns_wait_until_all_in_status('running')
+ print('all ready!')
+
+ osm1.ns_delete(ns_id1)
+ osm2.ns_delete(ns_id2)
+
+ osm1.ns_wait_until_all_in_status('terminated')
+ osm2.ns_wait_until_all_in_status('terminated')
+ print('all deleted!')
+
+finally:
+ api.stop()
+ net.stop()
--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
+
+from emuvim.api.osm.pre_configured_osm import PreConfiguredOSM
+
+from mininet.log import setLogLevel
+setLogLevel('debug')
+
+with PreConfiguredOSM() as osm:
+ osm.onboard_vnfd('vnfs/ping_vnf')
+ osm.onboard_vnfd('vnfs/pong_vnf')
+ nsd_id = osm.onboard_nsd('services/pingpong_ns')
+ ns_id = osm.ns_create('pingpong-test', nsd_id)
+
+ osm.ns_wait_until_all_in_status('running')
+ osm.ns_delete(ns_id)
+ osm.ns_wait_until_all_in_status('terminated')
--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
+
+from emuvim.api.osm.osm_component_base import OSMComponentBase
+from emuvim.api.util.process_utils import wait_until
+
+
+class Kafka(OSMComponentBase):
+ def __init__(self, net, ip, zookeeper_ip, version='latest', name_prefix=''):
+ OSMComponentBase.__init__(self)
+ self.instance = net.addDocker(
+ '{}kafka'.format(name_prefix), ip=ip, dimage='wurstmeister/kafka:%s' % version,
+ environment={'KAFKA_ADVERTISED_HOST_NAME': ip,
+ 'KAFKA_ADVERTISED_PORT': '9092',
+ 'KAFKA_ZOOKEEPER_CONNECT': '%s:2181' % zookeeper_ip,
+ 'KAFKA_CREATE_TOPICS': 'admin:1:1,ns:1:1,vim_account:1:1,wim_account:1:1,sdn:1:1,nsi:1:1'
+ })
+
+ def start(self):
+ OSMComponentBase.start(self)
+ wait_until('nc -z %s 9092' % self.instance.dcinfo['NetworkSettings']['IPAddress'])
--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
+
+import os
+
+import time
+
+from emuvim.api.osm.osm_component_base import OSMComponentBase
+from emuvim.api.util.docker_utils import wrap_debian_like
+
+
+class LCM(OSMComponentBase):
+ def __init__(self, net, ip, ro_ip, mongo_ip, kafka_ip,
+ vca_host=os.environ.get('VCA_HOST'),
+ vca_secret=os.environ.get('VCA_SECRET'),
+ version='latest',
+ name_prefix=''):
+ OSMComponentBase.__init__(self)
+ self.instance = net.addDocker(
+ '{}lcm'.format(name_prefix), ip=ip, dimage=wrap_debian_like('opensourcemano/lcm:%s' % version),
+ volumes=['osm_packages:/app/storage'],
+ environment={
+ 'OSMLCM_RO_HOST': ro_ip,
+ 'OSMLCM_VCA_HOST': vca_host,
+ 'OSMLCM_VCA_SECRET': vca_secret,
+ 'OSMLCM_DATABASE_URI': 'mongodb://%s:27017' % mongo_ip,
+ 'OSMLCM_MESSAGE_HOST': kafka_ip,
+ })
+
+ def start(self):
+ OSMComponentBase.start(self)
+ time.sleep(3)
--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
+
+from emuvim.api.osm.osm_component_base import OSMComponentBase
+from emuvim.api.util.docker_utils import wrap_debian_like
+
+
+class Mongo(OSMComponentBase):
+ def __init__(self, net, ip, version='latest', name_prefix=''):
+ OSMComponentBase.__init__(self)
+ self.instance = net.addDocker('{}mongo'.format(name_prefix), ip=ip, dimage=wrap_debian_like('mongo:%s' % version))
--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
+
+from emuvim.api.osm.osm_component_base import OSMComponentBase
+from emuvim.api.util.docker_utils import wrap_debian_like
+
+
+class Mysql(OSMComponentBase):
+ def __init__(self, net, ip, version='5', name_prefix=''):
+ OSMComponentBase.__init__(self)
+ self.instance = net.addDocker(
+ '{}ro-db'.format(name_prefix), ip=ip, dimage=wrap_debian_like('mysql:%s' % version),
+ environment={'MYSQL_ROOT_PASSWORD': 'TEST'})
--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
+
+import logging
+import os
+import subprocess
+
+import requests
+import time
+from pipes import quote
+from tempfile import NamedTemporaryFile
+
+import urllib3
+import yaml
+
+from emuvim.api.osm.osm_component_base import OSMComponentBase
+from emuvim.api.util.docker_utils import wrap_debian_like, DOCKER_HOST_IP
+from emuvim.api.util.path_utils import get_absolute_path
+from emuvim.api.util.process_utils import wait_until
+from mininet.log import debug
+
+# disables warnings about verify=False for TLS
+# since NBI runs with self-signed certificates this otherwise spams the log
+urllib3.disable_warnings()
+
+LOG = logging.getLogger(__name__)
+
+
+class NBI(OSMComponentBase):
+
+ def __init__(self, net, ip, mongo_ip, kafka_ip, version='latest', name_prefix=''):
+ OSMComponentBase.__init__(self)
+ self.instance = net.addDocker(
+ '{}nbi'.format(name_prefix), ip=ip, dimage=wrap_debian_like('opensourcemano/nbi:%s' % version),
+ volumes=['osm_packages:/app/storage'],
+ environment={'OSMNBI_DATABASE_URI': 'mongodb://%s:27017' % mongo_ip,
+ 'OSMNBI_MESSAGE_HOST': kafka_ip})
+ self._ip = self.instance.dcinfo['NetworkSettings']['IPAddress']
+
+ def start(self):
+ OSMComponentBase.start(self)
+ wait_until('nc -z %s 9999' % self._ip)
+
+ def _osm(self, command):
+ prefixed_command = 'osm %s' % command
+ debug('executing command: %s\n' % prefixed_command)
+ output = subprocess.check_output(prefixed_command, env={'OSM_HOSTNAME': self._ip}, shell=True)
+ debug('output: \n%s\n' % output)
+ return output
+
+ @staticmethod
+ def _create_archive(folder, tmp_file):
+ folder = get_absolute_path(folder)
+ parent_folder = os.path.dirname(folder)
+ basename = os.path.basename(folder)
+ subprocess.call('tar czf %s %s' % (quote(tmp_file.name), quote(basename)), cwd=parent_folder, shell=True)
+
+ def onboard_vnfd(self, folder):
+ try:
+ with NamedTemporaryFile() as tmp_archive:
+ self._create_archive(folder, tmp_archive)
+ return self._osm('vnfd-create %s' % quote(tmp_archive.name)).strip()
+ except subprocess.CalledProcessError as e:
+ raise RuntimeError('creating vnfd failed: %s' % e.output)
+
+ def onboard_nsd(self, folder):
+ try:
+ with NamedTemporaryFile() as tmp_archive:
+ self._create_archive(folder, tmp_archive)
+ return self._osm('nsd-create %s' % quote(tmp_archive.name)).strip()
+ except subprocess.CalledProcessError as e:
+ raise RuntimeError('creating nsd failed: %s' % e.output)
+
+ def _get_api_token(self):
+ token_request = requests.post('https://%s:9999/osm/admin/v1/tokens' % self._ip,
+ data={'username': 'admin', 'password': 'admin'}, verify=False)
+ if not token_request.ok:
+ raise RuntimeError('getting token failed with: %s' % token_request.text)
+ token = yaml.safe_load(token_request.text)
+ return token['id']
+
+ def _api_request_args(self):
+ return {'headers': {'Authorization': 'Bearer %s' % self._get_api_token()}, 'verify': False}
+
+ def _api_post_request(self, endpoint, data):
+ r = requests.post('https://%s:9999/%s' % (self._ip, endpoint),
+ json=data,
+ **self._api_request_args())
+ if not r.ok:
+ raise RuntimeError('POST request failed with: %s' % r.text)
+ result = yaml.safe_load(r.text)
+ return result
+
+ def _api_get_request(self, endpoint):
+ r = requests.get('https://%s:9999/%s' % (self._ip, endpoint),
+ **self._api_request_args())
+ if not r.ok:
+ raise RuntimeError('GET request failed with: %s' % r.text)
+ result = yaml.safe_load(r.text)
+ return result
+
+ def _api_delete_request(self, endpoint):
+ r = requests.delete('https://%s:9999/%s' % (self._ip, endpoint),
+ **self._api_request_args())
+ if not r.ok:
+ raise RuntimeError('DELETE request failed with: %s' % r.text)
+
+ def register_emulated_api(self, name, api):
+ output = self._osm('vim-create --name %s '
+ '--user username '
+ '--password password '
+ '--auth_url http://%s:%d/v2.0 '
+ '--tenant tenantName '
+ '--account_type openstack' % (
+ quote(name),
+ quote(DOCKER_HOST_IP),
+ api.port
+ ))
+ vim_id = output.strip()
+ while self._api_get_request('osm/admin/v1/vim_accounts/%s' % vim_id)['_admin']['detailed-status'] != 'Done':
+ time.sleep(1)
+ return vim_id
+
+ def ns_create(self, ns_name, nsd_id, vim_id):
+ result = self._api_post_request('osm/nslcm/v1/ns_instances_content', {
+ 'nsdId': nsd_id,
+ 'nsName': ns_name,
+ # dummy text since this cannot be empty
+ 'nsDescription': 'created by vim-emu',
+ 'vimAccountId': vim_id,
+ })
+ return result['id']
+
+ def ns_get(self, ns_id):
+ return self._api_get_request('osm/nslcm/v1/ns_instances_content/%s' % ns_id)
+
+ def ns_action(self, ns_id, vnf_member_index, action, args=None):
+ if args is None:
+ args = {}
+ result = self._api_post_request('osm/nslcm/v1/ns_instances/%s/action' % ns_id, {
+ 'vnf_member_index': str(vnf_member_index),
+ 'primitive': action,
+ 'primitive_params': args,
+ })
+ return result['id']
+
+ def ns_delete(self, ns_id):
+ self._api_delete_request('osm/nslcm/v1/ns_instances_content/%s' % ns_id)
+
+ def ns_list(self):
+ return self._api_get_request('osm/nslcm/v1/ns_instances_content')
+
+ @staticmethod
+ def _count_all_in_operational_status(ns_list, status):
+ return len(filter(lambda x: x['operational-status'] == status, ns_list))
+
+ def ns_wait_until_all_in_status(self, *statuses):
+ """Waits for all NSs to be in one of the specified stati.
+ Returns a tuple with the counts of the NSs in the invididual
+ stati in the same order as the specified stati"""
+
+ LOG.debug('Waiting for all NS to be in status {}'.format(statuses))
+ while True:
+ ns_list = self.ns_list()
+ state = ()
+ for status in statuses:
+ state += (self._count_all_in_operational_status(ns_list, status),)
+ number_correct = sum(state)
+ missing = len(ns_list) - number_correct
+ if missing == 0:
+ break
+ logging.debug('waiting for the status of %s services to change to %s' % (missing, statuses))
+ time.sleep(1)
+
+ logging.debug('all %d NSs in status %s' % (len(ns_list), statuses))
+ return state
--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
+
+import os
+
+from emuvim.api.openstack.resources.net import Net
+from emuvim.api.osm.kafka import Kafka
+from emuvim.api.osm.lcm import LCM
+from emuvim.api.osm.mongo import Mongo
+from emuvim.api.osm.mysql import Mysql
+from emuvim.api.osm.nbi import NBI
+from emuvim.api.osm.ro import RO
+from emuvim.api.osm.zookeeper import Zookeeper
+
+
+class OSM:
+ def __init__(self, net,
+ switch,
+ name='osm',
+ vca_host=os.environ.get('VCA_HOST'),
+ vca_secret=os.environ.get('VCA_SECRET'),
+ osm_version='releasefive-daily',
+ ip_start='10.0.0.100'):
+ ip_int = Net.ip_2_int(ip_start)
+ zookeeper_ip = ip_start
+ kafka_ip = Net.int_2_ip(ip_int + 1)
+ mongo_ip = Net.int_2_ip(ip_int + 2)
+ nbi_ip = Net.int_2_ip(ip_int + 3)
+ ro_db_ip = Net.int_2_ip(ip_int + 4)
+ ro_ip = Net.int_2_ip(ip_int + 5)
+ lcm_ip = Net.int_2_ip(ip_int + 6)
+
+ name_prefix = '%s-' % name
+ self.zookeeper = Zookeeper(net, '%s/16' % zookeeper_ip, name_prefix=name_prefix)
+ self.kafka = Kafka(net, '%s/16' % kafka_ip, zookeeper_ip, name_prefix=name_prefix)
+ self.mongo = Mongo(net, '%s/16' % mongo_ip, name_prefix=name_prefix)
+ self.nbi = NBI(net, '%s/16' % nbi_ip, mongo_ip, kafka_ip, version=osm_version, name_prefix=name_prefix)
+ self.ro_db = Mysql(net, '%s/16' % ro_db_ip, name_prefix=name_prefix)
+ self.ro = RO(net, '%s/16' % ro_ip, ro_db_ip, version=osm_version, name_prefix=name_prefix)
+ self.lcm = LCM(net, '%s/16' % lcm_ip, ro_ip, mongo_ip, kafka_ip,
+ vca_host, vca_secret, version=osm_version, name_prefix=name_prefix)
+
+ net.addLink(self.zookeeper.instance, switch)
+ net.addLink(self.kafka.instance, switch)
+ net.addLink(self.mongo.instance, switch)
+ net.addLink(self.nbi.instance, switch)
+ net.addLink(self.ro_db.instance, switch)
+ net.addLink(self.ro.instance, switch)
+ net.addLink(self.lcm.instance, switch)
+
+ def start(self):
+ self.zookeeper.start()
+ self.kafka.start()
+ self.mongo.start()
+ self.nbi.start()
+ self.ro_db.start()
+ self.ro.start()
+ self.lcm.start()
+
+ # forward api related calls
+ def onboard_vnfd(self, *args, **kwargs):
+ return self.nbi.onboard_vnfd(*args, **kwargs)
+
+ def onboard_nsd(self, *args, **kwargs):
+ return self.nbi.onboard_nsd(*args, **kwargs)
+
+ def register_emulated_api(self, *args, **kwargs):
+ return self.nbi.register_emulated_api(*args, **kwargs)
+
+ def ns_list(self):
+ return self.nbi.ns_list()
+
+ def ns_create(self, *args, **kwargs):
+ return self.nbi.ns_create(*args, **kwargs)
+
+ def ns_delete(self, *args, **kwargs):
+ return self.nbi.ns_delete(*args, **kwargs)
+
+ def ns_get(self, *args, **kwargs):
+ return self.nbi.ns_get(*args, **kwargs)
+
+ def ns_action(self, *args, **kwargs):
+ return self.nbi.ns_action(*args, **kwargs)
+
+ def ns_wait_until_all_in_status(self, *args, **kwargs):
+ return self.nbi.ns_wait_until_all_in_status(*args, **kwargs)
--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
+
+
+class OSMComponentBase:
+ def __init__(self):
+ self.instance = None
+
+ def start(self):
+ self.instance.start()
--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
+
+import os
+
+from emuvim.api.openstack.openstack_api_endpoint import OpenstackApiEndpoint
+from emuvim.api.osm.osm import OSM
+from emuvim.dcemulator.net import DCNetwork
+
+
+class PreConfiguredOSM:
+ def __init__(self,
+ vca_host=os.environ.get('VCA_HOST'),
+ vca_secret=os.environ.get('VCA_SECRET'),
+ osm_version='releasefive-daily'):
+ self.net = DCNetwork(monitor=False, enable_learning=True)
+ dc1 = self.net.addDatacenter("dc1")
+ self.api = OpenstackApiEndpoint("0.0.0.0", 6001)
+ self.api.connect_datacenter(dc1)
+ self.api.connect_dc_network(self.net)
+
+ s1 = self.net.addSwitch('s1')
+ self.osm = OSM(self.net, s1, vca_host=vca_host, vca_secret=vca_secret, osm_version=osm_version)
+ self.vim_emu_id = None
+
+ def __enter__(self):
+ self.start()
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.stop()
+
+ def start(self):
+ self.net.start()
+ self.api.start()
+ self.osm.start()
+ self.vim_emu_id = self.osm.register_emulated_api('emu-vim1', self.api)
+
+ def stop(self):
+ self.api.stop()
+ self.net.stop()
+
+ def ns_create(self, ns_name, nsd_id):
+ return self.osm.ns_create(ns_name, nsd_id, self.vim_emu_id)
+
+ # forward api related calls
+ def onboard_vnfd(self, *args, **kwargs):
+ return self.osm.onboard_vnfd(*args, **kwargs)
+
+ def onboard_nsd(self, *args, **kwargs):
+ return self.osm.onboard_nsd(*args, **kwargs)
+
+ def ns_list(self):
+ return self.osm.ns_list()
+
+ def ns_delete(self, *args, **kwargs):
+ return self.osm.ns_delete(*args, **kwargs)
+
+ def ns_get(self, *args, **kwargs):
+ return self.osm.ns_get(*args, **kwargs)
+
+ def ns_action(self, *args, **kwargs):
+ return self.osm.ns_action(*args, **kwargs)
+
+ def ns_wait_until_all_in_status(self, *args, **kwargs):
+ return self.osm.ns_wait_until_all_in_status(*args, **kwargs)
--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
+
+from emuvim.api.osm.osm_component_base import OSMComponentBase
+from emuvim.api.util.docker_utils import wrap_debian_like
+from emuvim.api.util.process_utils import wait_until
+
+
+class RO(OSMComponentBase):
+ def __init__(self, net, ip, db_ip, version='latest', name_prefix=''):
+ OSMComponentBase.__init__(self)
+ self.instance = net.addDocker(
+ '{}ro'.format(name_prefix), ip=ip, dimage=wrap_debian_like('opensourcemano/ro:%s' % version),
+ environment={'RO_DB_HOST': db_ip, 'RO_DB_ROOT_PASSWORD': 'TEST'})
+
+ def start(self):
+ OSMComponentBase.start(self)
+ wait_until('nc -z %s 9090' % self.instance.dcinfo['NetworkSettings']['IPAddress'])
--- /dev/null
+#!/usr/bin/env python2
+# Copyright (c) 2019 Erik Schilling
+# ALL RIGHTS RESERVED.
+#
+# 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.
+
+from emuvim.api.osm.osm_component_base import OSMComponentBase
+
+
+class Zookeeper(OSMComponentBase):
+ def __init__(self, net, ip, version='latest', name_prefix=''):
+ OSMComponentBase.__init__(self)
+ self.instance = net.addDocker(
+ '{}zk'.format(name_prefix),
+ ip=ip,
+ dimage='wurstmeister/zookeeper:%s' % version)
--- /dev/null
+import logging
+from io import BytesIO
+
+import docker
+
+from emuvim.api.util.path_utils import get_absolute_path
+
+
+def build_dockerfile_dir(folder, tag):
+ dcli = docker.from_env().api
+ folder = get_absolute_path(folder)
+ build_stream = dcli.build(folder, tag=tag)
+ logging.info('Docker build result:')
+ for line in build_stream:
+ logging.info(line)
+
+
+def suffix_tag_name(tag, suffix):
+ if ":" in tag:
+ return "%s_%s" % (tag, suffix)
+ return "%s:latest_%s" % (tag, suffix)
+
+
+def wrap_debian_like(image):
+ dcli = docker.from_env().api
+ dockerfile = '''
+ FROM %s
+ RUN apt update -y && apt install -y net-tools iputils-ping iproute
+ ''' % image
+ f = BytesIO(dockerfile.encode('utf-8'))
+ wrapper_name = suffix_tag_name(image, 'containernet_compatible')
+ logging.info('wrapping image: %s->%s' % (image, wrapper_name))
+ build_stream = dcli.build(fileobj=f, tag=wrapper_name)
+ build_result = [line for line in build_stream]
+ logging.debug('Docker build result:' + '\n'.join(build_result))
+ return wrapper_name
+
+
+# 172.17.0.1 is the ip of the docker0 interface on the host
+DOCKER_HOST_IP = '172.17.0.1'
--- /dev/null
+import os
+import sys
+
+
+def get_absolute_path(absolute_or_relative_to_main_path):
+ if os.path.isabs(absolute_or_relative_to_main_path):
+ return absolute_or_relative_to_main_path
+ return os.path.join(sys.path[0], absolute_or_relative_to_main_path)
--- /dev/null
+import logging
+import subprocess
+import time
+
+
+def wait_until(cmd):
+ logging.debug('waiting for %s\n' % cmd)
+ while subprocess.call(cmd, shell=True) != 0:
+ time.sleep(1)