X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=rwcal%2Fplugins%2Fvala%2Frwcal_openstack%2Frwcal_openstack.py;h=66859c71de823813b20da6df6ebf5345ff00710e;hb=f314b4af9744068a7ed7a6a6314220c3aa857523;hp=52bd574c701a391f486c470a48e274955462e242;hpb=411ef48f19a20a7a15d29c391c23a3bf6042e000;p=osm%2FSO.git diff --git a/rwcal/plugins/vala/rwcal_openstack/rwcal_openstack.py b/rwcal/plugins/vala/rwcal_openstack/rwcal_openstack.py index 52bd574c..66859c71 100644 --- a/rwcal/plugins/vala/rwcal_openstack/rwcal_openstack.py +++ b/rwcal/plugins/vala/rwcal_openstack/rwcal_openstack.py @@ -15,15 +15,14 @@ # limitations under the License. # -import contextlib import logging import os import subprocess import tempfile import yaml +import shlex import gi -gi.require_version('RwSdn', '1.0') gi.require_version('RwCal', '1.0') gi.require_version('RwcalYang', '1.0') @@ -33,23 +32,19 @@ import rift.rwcal.openstack as openstack_drv import rw_status import rift.cal.rwcal_status as rwcal_status import rwlogger -import neutronclient.common.exceptions as NeutronException -import keystoneclient.exceptions as KeystoneExceptions from gi.repository import ( GObject, RwCal, - RwSdn, # Vala package - RwsdnYang, RwTypes, RwcalYang) PREPARE_VM_CMD = "prepare_vm.py --auth_url {auth_url} --username {username} --password {password} --tenant_name {tenant_name} --region {region} --user_domain {user_domain} --project_domain {project_domain} --mgmt_network {mgmt_network} --server_id {server_id} --port_metadata " -rwstatus_exception_map = { IndexError: RwTypes.RwStatus.NOTFOUND, - KeyError: RwTypes.RwStatus.NOTFOUND, - NotImplementedError: RwTypes.RwStatus.NOT_IMPLEMENTED,} +rwstatus_exception_map = {IndexError: RwTypes.RwStatus.NOTFOUND, + KeyError: RwTypes.RwStatus.NOTFOUND, + NotImplementedError: RwTypes.RwStatus.NOT_IMPLEMENTED, } rwstatus = rw_status.rwstatus_from_exc_map(rwstatus_exception_map) rwcalstatus = rwcal_status.rwcalstatus_from_exc_map(rwstatus_exception_map) @@ -69,6 +64,8 @@ class OpenstackServerGroupError(Exception): class ImageUploadError(Exception): pass +class PrepareVduOnBoot(Exception): + pass class RwcalAccountDriver(object): """ @@ -78,9 +75,6 @@ class RwcalAccountDriver(object): self.log = logger try: self._driver = openstack_drv.OpenstackDriver(logger = self.log, **kwargs) - except (KeystoneExceptions.Unauthorized, KeystoneExceptions.AuthorizationFailure, - NeutronException.NotFound) as e: - raise except Exception as e: self.log.error("RwcalOpenstackPlugin: OpenstackDriver init failed. Exception: %s" %(str(e))) raise @@ -96,18 +90,29 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): def __init__(self): GObject.Object.__init__(self) - self._driver_class = openstack_drv.OpenstackDriver self.log = logging.getLogger('rwcal.openstack.%s' % RwcalOpenstackPlugin.instance_num) self.log.setLevel(logging.DEBUG) self._rwlog_handler = None self._account_drivers = dict() RwcalOpenstackPlugin.instance_num += 1 + def _get_account_key(self, account): + key = str() + for f in account.openstack.fields: + try: + key+= str(getattr(account.openstack, f)) + except: + pass + key += account.name + return key + def _use_driver(self, account): if self._rwlog_handler is None: raise UninitializedPluginError("Must call init() in CAL plugin before use.") - if account.name not in self._account_drivers: + acct_key = self._get_account_key(account) + + if acct_key not in self._account_drivers: self.log.debug("Creating OpenstackDriver") kwargs = dict(username = account.openstack.key, password = account.openstack.secret, @@ -122,7 +127,7 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): self._account_drivers[account.name] = drv return drv.driver else: - return self._account_drivers[account.name].driver + return self._account_drivers[acct_key].driver @rwstatus @@ -145,35 +150,12 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): Returns: Validation Code and Details String """ - status = RwcalYang.CloudConnectionStatus() - drv = self._use_driver(account) + status = RwcalYang.YangData_Rwcal_ConnectionStatus() try: + drv = self._use_driver(account) drv.validate_account_creds() - except KeystoneExceptions.Unauthorized as e: - self.log.error("Invalid credentials given for VIM account %s", account.name) - status.status = "failure" - status.details = "Invalid Credentials: %s" % str(e) - - except KeystoneExceptions.AuthorizationFailure as e: - self.log.error("Bad authentication URL given for VIM account %s. Given auth url: %s", - account.name, account.openstack.auth_url) - status.status = "failure" - status.details = "Invalid auth url: %s" % str(e) - - except NeutronException.NotFound as e: - self.log.error("Given management network %s could not be found for VIM account %s", - account.openstack.mgmt_network, - account.name) - status.status = "failure" - status.details = "mgmt network does not exist: %s" % str(e) - - except openstack_drv.ValidationError as e: - self.log.error("RwcalOpenstackPlugin: OpenstackDriver credential validation failed. Exception: %s", str(e)) - status.status = "failure" - status.details = "Invalid Credentials: %s" % str(e) - except Exception as e: - msg = "RwcalOpenstackPlugin: OpenstackDriver connection failed. Exception: %s" %(str(e)) + msg = "RwcalOpenstackPlugin: Exception: %s" %(str(e)) self.log.error(msg) status.status = "failure" status.details = msg @@ -339,7 +321,7 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): Returns: The the list of images in VimResources object """ - response = RwcalYang.VimResources() + response = RwcalYang.YangData_RwProject_Project_VimResources() drv = self._use_driver(account) try: images = drv.glance_image_list() @@ -392,11 +374,8 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): kwargs['image_id'] = vminfo.image_id ### If floating_ip is required and we don't have one, better fail before any further allocation - pool_name = None floating_ip = False if vminfo.has_field('allocate_public_address') and vminfo.allocate_public_address: - if account.openstack.has_field('floating_ip_pool'): - pool_name = account.openstack.floating_ip_pool floating_ip = True if vminfo.has_field('cloud_init') and vminfo.cloud_init.has_field('userdata'): @@ -433,7 +412,7 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): kwargs['availability_zone'] = None if vminfo.has_field('server_group'): - kwargs['scheduler_hints'] = {'group': vminfo.server_group } + kwargs['scheduler_hints'] = {'group': vminfo.server_group} else: kwargs['scheduler_hints'] = None @@ -502,7 +481,7 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): Returns: Protobuf Gi object for VM """ - vm = RwcalYang.VMInfoItem() + vm = RwcalYang.YangData_RwProject_Project_VimResources_VminfoList() vm.vm_id = vm_info['id'] vm.vm_name = vm_info['name'] vm.image_id = vm_info['image']['id'] @@ -532,10 +511,10 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): if key in vm.user_tags.fields: setattr(vm.user_tags, key, value) if 'OS-EXT-SRV-ATTR:host' in vm_info: - if vm_info['OS-EXT-SRV-ATTR:host'] != None: + if vm_info['OS-EXT-SRV-ATTR:host'] is not None: vm.host_name = vm_info['OS-EXT-SRV-ATTR:host'] if 'OS-EXT-AZ:availability_zone' in vm_info: - if vm_info['OS-EXT-AZ:availability_zone'] != None: + if vm_info['OS-EXT-AZ:availability_zone'] is not None: vm.availability_zone = vm_info['OS-EXT-AZ:availability_zone'] return vm @@ -549,7 +528,7 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): Returns: List containing VM information """ - response = RwcalYang.VimResources() + response = RwcalYang.YangData_RwProject_Project_VimResources() drv = self._use_driver(account) vms = drv.nova_server_list() for vm in vms: @@ -584,12 +563,17 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): flavor id """ drv = self._use_driver(account) - return drv.nova_flavor_create(name = flavor.name, - ram = flavor.vm_flavor.memory_mb, - vcpus = flavor.vm_flavor.vcpu_count, - disk = flavor.vm_flavor.storage_gb, - epa_specs = drv.utils.flavor.get_extra_specs(flavor)) - + try: + flavor_id = drv.nova_flavor_create(name = flavor.name, + ram = flavor.vm_flavor.memory_mb, + vcpus = flavor.vm_flavor.vcpu_count, + disk = flavor.vm_flavor.storage_gb, + epa_specs = drv.utils.flavor.get_extra_specs(flavor)) + except Exception as e: + self.log.error("Encountered exceptions during Flavor creation. Exception: %s", str(e)) + raise + + return flavor_id @rwstatus def do_delete_flavor(self, account, flavor_id): @@ -600,7 +584,11 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): flavor_id - id flavor of the VM """ drv = self._use_driver(account) - drv.nova_flavor_delete(flavor_id) + try: + drv.nova_flavor_delete(flavor_id) + except Exception as e: + self.log.error("Encountered exceptions during Flavor deletion. Exception: %s", str(e)) + raise @rwstatus(ret_on_failure=[[]]) @@ -613,11 +601,16 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): Returns: List of flavors """ - response = RwcalYang.VimResources() + response = RwcalYang.YangData_RwProject_Project_VimResources() drv = self._use_driver(account) - flavors = drv.nova_flavor_list() - for flv in flavors: - response.flavorinfo_list.append(drv.utils.flavor.parse_flavor_info(flv)) + try: + flavors = drv.nova_flavor_list() + for flv in flavors: + response.flavorinfo_list.append(drv.utils.flavor.parse_flavor_info(flv)) + except Exception as e: + self.log.error("Encountered exceptions during get-flavor-list. Exception: %s", str(e)) + raise + return response @rwstatus(ret_on_failure=[None]) @@ -632,8 +625,14 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): Flavor info item """ drv = self._use_driver(account) - flavor = drv.nova_flavor_get(id) - return drv.utils.flavor.parse_flavor_info(flavor) + try: + flavor = drv.nova_flavor_get(id) + response = drv.utils.flavor.parse_flavor_info(flavor) + except Exception as e: + self.log.error("Encountered exceptions during get-flavor. Exception: %s", str(e)) + raise + + return response def _fill_network_info(self, network_info, account): @@ -649,10 +648,10 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): Returns: Network info item """ - network = RwcalYang.NetworkInfoItem() + network = RwcalYang.YangData_RwProject_Project_VimResources_NetworkinfoList() network.network_name = network_info['name'] network.network_id = network_info['id'] - if ('provider:network_type' in network_info) and (network_info['provider:network_type'] != None): + if ('provider:network_type' in network_info) and (network_info['provider:network_type'] is not None): network.provider_network.overlay_type = network_info['provider:network_type'].upper() if ('provider:segmentation_id' in network_info) and (network_info['provider:segmentation_id']): network.provider_network.segmentation_id = network_info['provider:segmentation_id'] @@ -676,7 +675,7 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): Returns: List of networks """ - response = RwcalYang.VimResources() + response = RwcalYang.YangData_RwProject_Project_VimResources() drv = self._use_driver(account) networks = drv.neutron_network_list() for network in networks: @@ -726,10 +725,15 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): if network.provider_network.has_field('segmentation_id'): kwargs['segmentation_id'] = network.provider_network.segmentation_id - drv = self._use_driver(account) - network_id = drv.neutron_network_create(**kwargs) - drv.neutron_subnet_create(network_id = network_id, - cidr = network.subnet) + try: + drv = self._use_driver(account) + network_id = drv.neutron_network_create(**kwargs) + drv.neutron_subnet_create(network_id = network_id, + cidr = network.subnet) + except Exception as e: + self.log.exception("Exception %s occured during create-network", str(e)) + raise + return network_id @rwstatus @@ -756,7 +760,7 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): Returns: Port info item """ - port = RwcalYang.PortInfoItem() + port = RwcalYang.YangData_RwProject_Project_VimResources_PortinfoList() port.port_name = port_info['name'] port.port_id = port_info['id'] @@ -793,7 +797,7 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): Returns: Port info list """ - response = RwcalYang.VimResources() + response = RwcalYang.YangData_RwProject_Project_VimResources() drv = self._use_driver(account) ports = drv.neutron_port_list(*{}) for port in ports: @@ -899,17 +903,25 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): Returns: A kwargs dictionary for glance operation """ - drv = self._use_driver(account) + network_id = None try: kwargs = drv.utils.network.make_virtual_link_args(link_params) network_id = drv.neutron_network_create(**kwargs) + drv.utils.network.prepare_virtual_link(link_params, network_id) except Exception as e: - self.log.error("Encountered exceptions during network creation. Exception: %s", str(e)) - raise - - kwargs = drv.utils.network.make_subnet_args(link_params, network_id) - drv.neutron_subnet_create(**kwargs) + self.log.exception("Encountered exceptions during network creation. Exception: %s", str(e)) + # This is to delete the network if neutron_subnet_create fails after creation of network + # Note:- Any subnet created will be implicitly deleted. + if network_id is not None: + try: + drv.neutron_network_delete(network_id) + except Exception as delete_exception: + self.log.debug("Exception while deleting the network after failure of neutron_subnet_create or make_subnet_args: %s", str(delete_exception)) + # Raising exception so that the Exception is propagated to Resmgr. + # This fixes the UI Stuck at Vl-Init-Phase. + raise Exception(str(e) + " --> " + str(delete_exception)) + raise e return network_id @@ -944,7 +956,7 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): link_id - id for the virtual-link Returns: - Object of type RwcalYang.VirtualLinkInfoParams + Object of type RwcalYang.YangData_RwProject_Project_VnfResources_VirtualLinkInfoList """ drv = self._use_driver(account) try: @@ -961,6 +973,34 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): raise return virtual_link + @rwstatus(ret_on_failure=[None]) + def do_get_virtual_link_by_name(self, account, link_name): + """Get information about virtual link. + + Arguments: + account - a cloud account + link_name - name for the virtual-link + + Returns: + Object of type RwcalYang.YangData_RwProject_Project_VnfResources_VirtualLinkInfoList + """ + drv = self._use_driver(account) + try: + network = drv.neutron_network_get_by_name(link_name) + if network: + port_list = drv.neutron_port_list(**{'network_id': network['id']}) + if 'subnets' in network and network['subnets']: + subnet = drv.neutron_subnet_get(network['subnets'][0]) + else: + subnet = None + virtual_link = drv.utils.network.parse_cloud_virtual_link_info(network, port_list, subnet) + else: + return None + except Exception as e: + self.log.exception("Exception %s occured during virtual-link-get-by-name", str(e)) + raise + return virtual_link + @rwstatus(ret_on_failure=[None]) def do_get_virtual_link_list(self, account): """Get information about all the virtual links @@ -969,9 +1009,9 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): account - a cloud account Returns: - A list of objects of type RwcalYang.VirtualLinkInfoParams + A list of objects of type RwcalYang.YangData_RwProject_Project_VnfResources_VirtualLinkInfoList """ - vnf_resources = RwcalYang.VNFResources() + vnf_resources = RwcalYang.YangData_RwProject_Project_VnfResources() drv = self._use_driver(account) try: networks = drv.neutron_network_list() @@ -996,37 +1036,53 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): Arguments: account - a cloud account - vdu_init - information about VDU to create (RwcalYang.VDUInitParams) + vdu_init - information about VDU to create (RwcalYang.YangData_RwProject_Project_VduInitParams) Returns: The vdu_id """ drv = self._use_driver(account) + vdu_prepared = True try: kwargs = drv.utils.compute.make_vdu_create_args(vdu_init, account) vm_id = drv.nova_server_create(**kwargs) - self.prepare_vdu_on_boot(account, vm_id, vdu_init) + vdu_prepared_on_boot = self.prepare_vdu_on_boot(account, vm_id, vdu_init) + vdu_prepared = vdu_prepared_on_boot["status"] except Exception as e: self.log.exception("Exception %s occured during create-vdu", str(e)) raise + + if vdu_prepared is False: + drv.utils.compute.perform_vdu_network_cleanup(vm_id) + drv.nova_server_delete(vm_id) + self.log.exception("Cleaning Up VDU as Prepare Vdu Failed : %s", vdu_prepared_on_boot["exception"]) + raise PrepareVduOnBoot(vdu_prepared_on_boot["exception"]) return vm_id def prepare_vdu_on_boot(self, account, server_id, vdu_params): - cmd = PREPARE_VM_CMD.format(auth_url = account.openstack.auth_url, - username = account.openstack.key, - password = account.openstack.secret, - tenant_name = account.openstack.tenant, - region = account.openstack.region, - user_domain = account.openstack.user_domain, - project_domain = account.openstack.project_domain, - mgmt_network = account.openstack.mgmt_network, - server_id = server_id) + if vdu_params.mgmt_network is not None: + mgmt_network_param = vdu_params.mgmt_network + else: + mgmt_network_param = account.openstack.mgmt_network + + # Adding shell quote to all parameters in case they contain special characters. + cmd = PREPARE_VM_CMD.format(auth_url = shlex.quote(account.openstack.auth_url), + username = shlex.quote(account.openstack.key), + password = shlex.quote(account.openstack.secret), + tenant_name = shlex.quote(account.openstack.tenant), + region = shlex.quote(account.openstack.region), + user_domain = shlex.quote(account.openstack.user_domain), + project_domain = shlex.quote(account.openstack.project_domain), + mgmt_network = shlex.quote(mgmt_network_param), + server_id = shlex.quote(server_id)) vol_list = list() + + vdu_prepared = {"status": True, "exception": None} if vdu_params.has_field('allocate_public_address') and vdu_params.allocate_public_address: - cmd += " --floating_ip" if account.openstack.has_field('floating_ip_pool'): + cmd += " --floating_ip" cmd += (" --pool_name " + account.openstack.floating_ip_pool) if vdu_params.has_field('volumes'): @@ -1038,19 +1094,34 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: yaml.dump(vol_list, tmp_file) cmd += (" --vol_metadata {}").format(tmp_file.name) - + + exec_path = 'python3 ' + os.path.dirname(openstack_drv.__file__) - exec_cmd = exec_path+'/'+cmd + exec_cmd = exec_path + '/' + cmd self.log.info("Running command: %s" %(exec_cmd)) - subprocess.call(exec_cmd, shell=True) - + + # The return code for the subprocess is always 0. Hence using check_output + # for validating the success/failure of the script + # The check_output returns False or True on the basis of exception + # handling in prepare_vm.py + prepare_vm_status = subprocess.check_output(exec_cmd, shell=True) + + # prepare_vm_status is a string in the format of True/False+ error message + # if any. This is to propagate the detailed exception to the callers. + vdu_status_elems = prepare_vm_status.decode("utf-8").split("+") + if(vdu_status_elems[0] == 'False'): + self.log.exception("Exception occured while preparing vdu after boot") + vdu_prepared = {"status": False, "exception": vdu_status_elems[1]} + + return vdu_prepared + @rwstatus def do_modify_vdu(self, account, vdu_modify): """Modify Properties of existing virtual deployment unit Arguments: account - a cloud account - vdu_modify - Information about VDU Modification (RwcalYang.VDUModifyParams) + vdu_modify - Information about VDU Modification (RwcalYang.YangData_RwProject_Project_VduModifyParams) """ drv = self._use_driver(account) ### First create required number of ports aka connection points @@ -1097,29 +1168,33 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): raise - @rwstatus(ret_on_failure=[None]) - def do_get_vdu(self, account, vdu_id): + @rwcalstatus(ret_on_failure=[None]) + def do_get_vdu(self, account, vdu_id, mgmt_network): """Get information about a virtual deployment unit. Arguments: account - a cloud account vdu_id - id for the vdu + mgmt_network - mgmt_network if provided in NSD VL Returns: - Object of type RwcalYang.VDUInfoParams + Object of type RwcalYang.YangData_RwProject_Project_VnfResources_VduInfoList """ + if mgmt_network not in [None, ""]: + account.openstack.mgmt_network = mgmt_network + drv = self._use_driver(account) try: vm_info = drv.nova_server_get(vdu_id) vdu_info = drv.utils.compute.parse_cloud_vdu_info(vm_info) except Exception as e: - self.log.exception("Exception %s occured during get-vdu", str(e)) - raise + self.log.debug("Exception occured during get-vdu: %s", str(e)) + raise return vdu_info - @rwstatus(ret_on_failure=[None]) + @rwcalstatus(ret_on_failure=[None]) def do_get_vdu_list(self, account): """Get information about all the virtual deployment units @@ -1127,9 +1202,9 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): account - a cloud account Returns: - A list of objects of type RwcalYang.VDUInfoParams + A list of objects of type RwcalYang.YangData_RwProject_Project_VnfResources_VduInfoList """ - vnf_resources = RwcalYang.VNFResources() + vnf_resources = RwcalYang.YangData_RwProject_Project_VnfResources() drv = self._use_driver(account) try: vms = drv.nova_server_list() @@ -1137,181 +1212,8 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud): vdu = drv.utils.compute.parse_cloud_vdu_info(vm) vnf_resources.vdu_info_list.append(vdu) except Exception as e: - self.log.exception("Exception %s occured during get-vdu-list", str(e)) - raise + self.log.debug("Exception occured during get-vdu-list: %s", str(e)) + raise return vnf_resources -class SdnOpenstackPlugin(GObject.Object, RwSdn.Topology): - instance_num = 1 - def __init__(self): - GObject.Object.__init__(self) - self._driver_class = openstack_drv.OpenstackDriver - self.log = logging.getLogger('rwsdn.openstack.%s' % SdnOpenstackPlugin.instance_num) - self.log.setLevel(logging.DEBUG) - - self._rwlog_handler = None - SdnOpenstackPlugin.instance_num += 1 - - @contextlib.contextmanager - def _use_driver(self, account): - if self._rwlog_handler is None: - raise UninitializedPluginError("Must call init() in CAL plugin before use.") - - with rwlogger.rwlog_root_handler(self._rwlog_handler): - try: - drv = self._driver_class(username = account.openstack.key, - password = account.openstack.secret, - auth_url = account.openstack.auth_url, - tenant_name = account.openstack.tenant, - mgmt_network = account.openstack.mgmt_network, - cert_validate = account.openstack.cert_validate ) - except Exception as e: - self.log.error("SdnOpenstackPlugin: OpenstackDriver init failed. Exception: %s" %(str(e))) - raise - - yield drv - - @rwstatus - def do_init(self, rwlog_ctx): - self._rwlog_handler = rwlogger.RwLogger( - category="rw-cal-log", - subcategory="openstack", - log_hdl=rwlog_ctx, - ) - self.log.addHandler(self._rwlog_handler) - self.log.propagate = False - - @rwstatus(ret_on_failure=[None]) - def do_validate_sdn_creds(self, account): - """ - Validates the sdn account credentials for the specified account. - Performs an access to the resources using Keystone API. If creds - are not valid, returns an error code & reason string - - @param account - a SDN account - - Returns: - Validation Code and Details String - """ - status = RwsdnYang.SdnConnectionStatus() - try: - with self._use_driver(account) as drv: - drv.validate_account_creds() - - except openstack_drv.ValidationError as e: - self.log.error("SdnOpenstackPlugin: OpenstackDriver credential validation failed. Exception: %s", str(e)) - status.status = "failure" - status.details = "Invalid Credentials: %s" % str(e) - - except Exception as e: - msg = "SdnOpenstackPlugin: OpenstackDriver connection failed. Exception: %s" %(str(e)) - self.log.error(msg) - status.status = "failure" - status.details = msg - - else: - status.status = "success" - status.details = "Connection was successful" - - return status - - @rwstatus(ret_on_failure=[""]) - def do_create_vnffg_chain(self, account,vnffg): - """ - Creates Service Function chain in ODL - - @param account - a SDN account - - """ - self.log.debug('Received Create VNFFG chain for account {}, chain {}'.format(account,vnffg)) - with self._use_driver(account) as drv: - port_list = list() - vnf_chain_list = sorted(vnffg.vnf_chain_path, key = lambda x: x.order) - prev_vm_id = None - for path in vnf_chain_list: - if prev_vm_id and path.vnfr_ids[0].vdu_list[0].vm_id == prev_vm_id: - prev_entry = port_list.pop() - port_list.append((prev_entry[0],path.vnfr_ids[0].vdu_list[0].port_id)) - prev_vm_id = None - else: - prev_vm_id = path.vnfr_ids[0].vdu_list[0].vm_id - port_list.append((path.vnfr_ids[0].vdu_list[0].port_id,path.vnfr_ids[0].vdu_list[0].port_id)) - vnffg_id = drv.create_port_chain(vnffg.name,port_list) - return vnffg_id - - @rwstatus - def do_terminate_vnffg_chain(self, account,vnffg_id): - """ - Terminate Service Function chain in ODL - - @param account - a SDN account - """ - self.log.debug('Received terminate VNFFG chain for id %s ', vnffg_id) - with self._use_driver(account) as drv: - drv.delete_port_chain(vnffg_id) - - @rwstatus(ret_on_failure=[None]) - def do_create_vnffg_classifier(self, account, vnffg_classifier): - """ - Add VNFFG Classifier - - @param account - a SDN account - """ - self.log.debug('Received Create VNFFG classifier for account {}, classifier {}'.format(account,vnffg_classifier)) - protocol_map = {1:'ICMP',6:'TCP',17:'UDP'} - flow_classifier_list = list() - with self._use_driver(account) as drv: - for rule in vnffg_classifier.match_attributes: - classifier_name = vnffg_classifier.name + '_' + rule.name - flow_dict = {} - for field, value in rule.as_dict().items(): - if field == 'ip_proto': - flow_dict['protocol'] = protocol_map.get(value,None) - elif field == 'source_ip_address': - flow_dict['source_ip_prefix'] = value - elif field == 'destination_ip_address': - flow_dict['destination_ip_prefix'] = value - elif field == 'source_port': - flow_dict['source_port_range_min'] = value - flow_dict['source_port_range_max'] = value - elif field == 'destination_port': - flow_dict['destination_port_range_min'] = value - flow_dict['destination_port_range_max'] = value - if vnffg_classifier.has_field('port_id'): - flow_dict['logical_source_port'] = vnffg_classifier.port_id - flow_classifier_id = drv.create_flow_classifer(classifier_name, flow_dict) - flow_classifier_list.append(flow_classifier_id) - drv.update_port_chain(vnffg_classifier.rsp_id,flow_classifier_list) - return flow_classifier_list - - @rwstatus(ret_on_failure=[None]) - def do_terminate_vnffg_classifier(self, account, vnffg_classifier_list): - """ - Add VNFFG Classifier - - @param account - a SDN account - """ - self.log.debug('Received terminate VNFFG classifier for id %s ', vnffg_classifier_list) - with self._use_driver(account) as drv: - for classifier_id in vnffg_classifier_list: - drv.delete_flow_classifier(classifier_id) - - @rwstatus(ret_on_failure=[None]) - def do_get_vnffg_rendered_paths(self, account): - """ - Get ODL Rendered Service Path List (SFC) - - @param account - a SDN account - """ - self.log.debug('Received get VNFFG rendered path for account %s ', account) - vnffg_rsps = RwsdnYang.VNFFGRenderedPaths() - with self._use_driver(account) as drv: - port_chain_list = drv.get_port_chain_list() - for port_chain in port_chain_list: - #rsp = vnffg_rsps.vnffg_rendered_path.add() - #rsp.name = port_chain['name'] - pass - return vnffg_rsps - -