--- /dev/null
+
+#
+# Copyright 2016 RIFT.IO Inc
+#
+# 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
+from gi import require_version
+require_version('RwCal', '1.0')
+import rift.rwcal.openmano_vimconnector as vimconn_openvim
+import contextlib
+import requests
+import paramiko
+import os
+import uuid
+
+from gi.repository import (
+ GObject,
+ RwCal,
+ RwTypes,
+ RwcalYang)
+
+import rw_status
+import rift.cal.rwcal_status as rwcal_status
+import rwlogger
+
+logger = logging.getLogger('rwcal.openmano_vimconnector')
+
+class UnknownAccountError(Exception):
+ pass
+
+class OpenvimCALOperationFailure(Exception):
+ pass
+
+class MissingFileError(Exception):
+ pass
+
+
+class ImageLocationError(Exception):
+ pass
+
+class UninitializedPluginError(Exception):
+ pass
+
+rwstatus_exception_map = {IndexError: RwTypes.RwStatus.NOTFOUND,
+ KeyError: RwTypes.RwStatus.NOTFOUND,
+ UnknownAccountError: RwTypes.RwStatus.NOTFOUND,
+ MissingFileError: RwTypes.RwStatus.NOTFOUND,
+ }
+
+rwstatus = rw_status.rwstatus_from_exc_map(rwstatus_exception_map)
+rwcalstatus = rwcal_status.rwcalstatus_from_exc_map(rwstatus_exception_map)
+
+
+class RwcalOpenmanoVimConnector(GObject.Object, RwCal.Cloud):
+ """Stub implementation the CAL VALA methods for Openmano. """
+
+ instance_num = 1
+ def __init__(self):
+ GObject.Object.__init__(self)
+ self._driver_class = vimconn_openvim.vimconnector
+ self.log = logging.getLogger('rwcal.openmano_vimconnector.%s' % RwcalOpenmanoVimConnector.instance_num)
+ self.log.setLevel(logging.DEBUG)
+ self._rwlog_handler = None
+ self._tenant_name = None
+ RwcalOpenmanoVimConnector.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:
+ if self._tenant_name != account.openvim.tenant_name:
+ tmp_drv = self._driver_class(uuid = '',
+ name = '',
+ #tenant_id = account.openvim.tenant_id,
+ tenant_id = '',
+ tenant_name = '',
+ url ='http://{}:{}/openvim'.format(account.openvim.host,account.openvim.port),
+ url_admin = '')
+ tenant_dict = {'name':account.openvim.tenant_name}
+ tenant_list = tmp_drv.get_tenant_list(tenant_dict)
+ if len(tenant_list) == 0:
+ tmp_drv.new_tenant(account.openvim.tenant_name,"default tenant")
+ self._tenant_name = account.openvim.tenant_name
+ else:
+ self._tenant_name = account.openvim.tenant_name
+
+
+ drv = self._driver_class(uuid = '',
+ name = '',
+ #tenant_id = account.openvim.tenant_id,
+ tenant_id = '',
+ tenant_name = account.openvim.tenant_name,
+ url ='http://{}:{}/openvim'.format(account.openvim.host,account.openvim.port),
+ url_admin = '')
+
+ except Exception as e:
+ self.log.error("RwcalOpenmanoVimConnectorPlugin: VimConnector init failed. Exception: %s" %(str(e)))
+ raise
+
+ yield drv
+
+ @rwstatus
+ def do_init(self, rwlog_ctx):
+ if not any(isinstance(h, rwlogger.RwLogger) for h in logger.handlers):
+ logger.addHandler(
+ rwlogger.RwLogger(
+ category="rw-cal-log",
+ subcategory="openmano_vimconnector",
+ log_hdl=rwlog_ctx,
+ )
+ )
+
+ @rwstatus(ret_on_failure=[None])
+ def do_validate_cloud_creds(self, account):
+ """
+ Validates the cloud account credentials for the specified account.
+ If creds are not valid, returns an error code & reason string
+ Arguments:
+ account - a cloud account to validate
+
+ Returns:
+ Validation Code and Details String
+ """
+ status = RwcalYang.CloudConnectionStatus()
+ url = 'http://{}:{}/openvim/'.format(account.openvim.host,account.openvim.port)
+ try:
+ r=requests.get(url,timeout=3)
+ r.raise_for_status()
+ except requests.exceptions.HTTPError as e:
+ self.log.error("OpenvimConnectorPlugin: Openvim account credential validation failed. Exception: %s", str(e))
+ status.status = "failure"
+ status.details = "Invalid Credentials: %s" % str(e)
+ except Exception as e:
+ self.log.error("OpenvimConnectorPlugin: Openvim connection failed. Exception: %s", str(e))
+ status.status = "failure"
+ status.details = "Connection Failed (Invlaid URL): %s" % str(e)
+ else:
+ self.log.debug("Openvim Successfully connected")
+ status.status = "success"
+ status.details = "Connection was successful"
+
+ return status
+
+ @rwstatus(ret_on_failure=[None])
+ def do_get_management_network(self, account):
+ raise NotImplementedError()
+
+ @rwstatus
+ def do_create_tenant(self, account, name):
+ with self._use_driver(account) as drv:
+ return drv.new_tenant(name, "New CAL teannt");
+
+ @rwstatus
+ def do_delete_tenant(self, account, tenant_id):
+ with self._use_driver(account) as drv:
+ drv.delete_tenant(tenant_id);
+
+ @staticmethod
+ def _fill_tenant_info(tenant_info):
+ """Create a GI object from tenant info dictionary
+
+ Converts tenant information dictionary object returned by openmano vimconnector
+ driver into Protobuf Gi Object
+
+ Arguments:
+ tenant_info - tenant information dictionary object
+
+ Returns:
+ The TenantInfoItem
+ """
+ tenant = RwcalYang.TenantInfoItem()
+ tenant.tenant_name = tenant_info['name']
+ tenant.tenant_id = tenant_info['id']
+ return tenant
+
+ @rwstatus(ret_on_failure=[[]])
+ def do_get_tenant_list(self, account):
+ response = RwcalYang.VimResources()
+ with self._use_driver(account) as drv:
+ tenants = drv.get_tenant_list()
+ for tenant in tenants:
+ response.tenantinfo_list.append(RwcalOpenmanoVimConnector._fill_tenant_info(tenant))
+ return response
+
+ @rwstatus
+ def do_create_role(self, account, name):
+ raise NotImplementedError()
+
+ @rwstatus
+ def do_delete_role(self, account, role_id):
+ raise NotImplementedError()
+
+ @rwstatus(ret_on_failure=[[]])
+ def do_get_role_list(self, account):
+ raise NotImplementedError()
+
+ @rwstatus(ret_on_failure=[None])
+ def do_create_image(self, account, image):
+ with self._use_driver(account) as drv:
+ try:
+ # If the use passed in a file descriptor, use that to
+ # upload the image.
+ if image.has_field("fileno"):
+ new_fileno = os.dup(image.fileno)
+ hdl = os.fdopen(new_fileno, 'rb')
+ else:
+ hdl = open(image.location, "rb")
+ except Exception as e:
+ self.log.error("Could not open file for upload. Exception received: %s", str(e))
+ raise
+
+ tpt = paramiko.Transport((account.openvim.host, 22))
+ try:
+ tpt.connect(username=account.openvim.image_management.username,
+ password=account.openvim.image_management.password)
+ except Exception as e:
+ self.log.error('Could not connect to openvim host: %s. Exception: %s', account.openvim.host, e)
+ return
+
+ sftp = paramiko.SFTPClient.from_transport(tpt)
+ destination = account.openvim.image_management.image_directory_path.rstrip('/')+'/'+image.name
+ with hdl as fd:
+ try:
+ sftp.putfo(fd, destination)
+ except Exception as e:
+ self.log.warn('*** Caught exception: %s: %s', e.__class__, e)
+ finally:
+ sftp.close()
+ tpt.close()
+
+ image_dict = {}
+ image_dict['name'] = image.name
+ image_dict['location'] = destination
+ image_id = drv.new_image(image_dict)
+ return image_id
+
+ @rwstatus
+ def do_delete_image(self, account, image_id):
+ with self._use_driver(account) as drv:
+ drv.delete_image(image_id)
+
+ @staticmethod
+ def _fill_image_info(img_info):
+ img = RwcalYang.ImageInfoItem()
+ img.name = img_info['name']
+ img.id = img_info['id']
+ img.location = img_info['path']
+ if img_info['status'] == 'ACTIVE':
+ img.state = 'active'
+ else:
+ img.state = 'inactive'
+ return img
+
+ @rwstatus(ret_on_failure=[None])
+ def do_get_image(self, account, image_id):
+ with self._use_driver(account) as drv:
+ image = drv.get_image(image_id)
+ return RwcalOpenmanoVimConnector._fill_image_info(image)
+
+ @rwstatus(ret_on_failure=[[]])
+ def do_get_image_list(self, account):
+ response = RwcalYang.VimResources()
+ with self._use_driver(account) as drv:
+ images = drv.get_image_list()
+ for img in images:
+ image_info = drv.get_image(img['id'])
+ response.imageinfo_list.append(RwcalOpenmanoVimConnector._fill_image_info(image_info))
+ return response
+
+ @rwstatus
+ def do_create_vm(self, account, vm):
+ raise NotImplementedError()
+
+ @rwstatus
+ def do_start_vm(self, account, vm_id):
+ raise NotImplementedError()
+
+ @rwstatus
+ def do_stop_vm(self, account, vm_id):
+ raise NotImplementedError()
+
+ @rwstatus
+ def do_delete_vm(self, account, vm_id):
+ raise NotImplementedError()
+
+ @rwstatus
+ def do_reboot_vm(self, account, vm_id):
+ raise NotImplementedError()
+
+ @rwstatus(ret_on_failure=[[]])
+ def do_get_vm_list(self, account):
+ return RwcalYang.VimResources()
+
+ def _fill_flavor_create_attributes(flavor):
+ flavor_dict = dict()
+ flavor_dict['name'] = flavor.name
+ flavor_dict['ram'] = flavor.vm_flavor.memory_mb
+ flavor_dict['disk'] = flavor.vm_flavor.storage_gb
+ flavor_dict['vcpus'] = flavor.vm_flavor.vcpu_count
+ return flavor_dict
+
+ @rwstatus
+ def do_create_flavor(self, account, flavor):
+ with self._use_driver(account) as drv:
+ flavor_dict = RwcalOpenmanoVimConnector._fill_flavor_create_attributes(flavor)
+ flavor_id = drv.new_flavor(flavor_dict)
+ return flavor_id
+
+ @rwstatus
+ def do_delete_flavor(self, account, flavor_id):
+ with self._use_driver(account) as drv:
+ drv.delete_flavor(flavor_id)
+
+ @staticmethod
+ def _fill_epa_attributes(flavor, flavor_info):
+ if 'ram' in flavor_info and flavor_info['ram']:
+ getattr(flavor, 'vm_flavor').memory_mb = flavor_info.get('ram',0)
+ if 'disk' in flavor_info and flavor_info['disk']:
+ getattr(flavor, 'vm_flavor').storage_gb = flavor_info.get('disk',0)
+ if 'vcpus' in flavor_info and flavor_info['vcpus']:
+ getattr(flavor, 'vm_flavor').vcpu_count = flavor_info.get('vcpus',0)
+
+ if not 'extended' in flavor_info or flavor_info['extended'] is None:
+ return
+ getattr(flavor,'guest_epa').numa_node_policy.node_cnt = len(flavor_info['extended']['numas'])
+ for attr in flavor_info['extended']['numas']:
+ numa_node = getattr(flavor,'guest_epa').numa_node_policy.node.add()
+ numa_node.memory_mb = attr.get('memory',0)*1024
+ #getattr(flavor, 'host_epa').cpu_core_thread_count =
+
+ @staticmethod
+ def _fill_flavor_info(flavor_info):
+ flavor = RwcalYang.FlavorInfoItem()
+ flavor.name = flavor_info['name']
+ flavor.id = flavor_info['id']
+ RwcalOpenmanoVimConnector._fill_epa_attributes(flavor, flavor_info)
+ return flavor
+
+ @rwstatus(ret_on_failure=[None])
+ def do_get_flavor(self, account, flavor_id):
+ with self._use_driver(account) as drv:
+ flavor = drv.get_flavor(flavor_id)
+ return RwcalOpenmanoVimConnector._fill_flavor_info(flavor)
+
+
+ @rwstatus(ret_on_failure=[[]])
+ def do_get_flavor_list(self, account):
+ response = RwcalYang.VimResources()
+ with self._use_driver(account) as drv:
+ flavors = drv.get_flavor_list()
+ for flav in flavors:
+ flav_info = drv.get_flavor(flav['id'])
+ response.flavorinfo_list.append(RwcalOpenmanoVimConnector._fill_flavor_info(flav_info))
+ return response
+
+ @rwstatus
+ def do_add_host(self, account, host):
+ raise NotImplementedError()
+
+ @rwstatus
+ def do_remove_host(self, account, host_id):
+ raise NotImplementedError()
+
+ @rwstatus(ret_on_failure=[None])
+ def do_get_host(self, account, host_id):
+ raise NotImplementedError()
+
+ @rwstatus(ret_on_failure=[[]])
+ def do_get_host_list(self, account):
+ raise NotImplementedError()
+
+ @rwstatus
+ def do_create_port(self, account, port):
+ raise NotImplementedError()
+
+ @rwstatus
+ def do_delete_port(self, account, port_id):
+ raise NotImplementedError()
+
+ @rwstatus(ret_on_failure=[None])
+ def do_get_port(self, account, port_id):
+ raise NotImplementedError()
+
+ @rwstatus(ret_on_failure=[[]])
+ def do_get_port_list(self, account):
+ return RwcalYang.VimResources()
+
+ @rwstatus
+ def do_create_network(self, account, network):
+ with self._use_driver(account) as drv:
+ network_id = drv.new_network(network.name,'bridge_man')
+ return network_id
+
+ @rwstatus
+ def do_delete_network(self, account, network_id):
+ with self._use_driver(account) as drv:
+ drv.delete_network(network_id)
+
+ def _fill_network_info(self, network_info):
+ network = RwcalYang.NetworkInfoItem()
+ network.network_name = network_info['name']
+ network.network_id = network_info['id']
+ if ('provider:physical' in network_info) and (network_info['provider:physical']):
+ network.provider_network.physical_network = network_info['provider:physical'].upper()
+ if ('provider:vlan' in network_info) and (network_info['provider:vlan']):
+ network.provider_network.segmentation_id = network_info['provider:vlan']
+ network.provider_network.overlay_type = 'vlan'
+ return network
+
+ @rwstatus(ret_on_failure=[None])
+ def do_get_network(self, account, network_id):
+ with self._use_driver(account) as drv:
+ network = drv.get_network(id)
+ return self._fill_network_info(network)
+
+ @rwstatus(ret_on_failure=[[]])
+ def do_get_network_list(self, account):
+ response = RwcalYang.VimResources()
+ with self._use_driver(account) as drv:
+ networks = drv.get_network_list()
+ for network in networks:
+ response.networkinfo_list.append(self._fill_network_info(network))
+ return response
+
+ @rwcalstatus(ret_on_failure=[""])
+ def do_create_virtual_link(self, account, link_params):
+ with self._use_driver(account) as drv:
+ net = dict()
+ if link_params.provider_network.physical_network is not None:
+ net['provider:physical'] = link_params.provider_network.physical_network
+ #else:
+ # net['provider:physical'] = 'default'
+ if link_params.provider_network.overlay_type == 'VLAN' and link_params.provider_network.segmentation_id:
+ net['provider:vlan'] = link_params.provider_network.segmentation_id
+ network_id = drv.new_network(link_params.name,'bridge_man',shared=False,**net)
+ return network_id
+
+ @rwstatus
+ def do_delete_virtual_link(self, account, link_id):
+ with self._use_driver(account) as drv:
+ drv.delete_network(link_id)
+
+
+ @staticmethod
+ def _fill_connection_point_info(c_point, port_info):
+ c_point.name = port_info['name']
+ c_point.connection_point_id = port_info['id']
+ if 'ip_address' in port_info:
+ c_point.ip_address = port_info['ip_address']
+ if port_info['status'] == 'ACTIVE':
+ c_point.state = 'active'
+ else:
+ c_point.state = 'inactive'
+ if 'network_id' in port_info:
+ c_point.virtual_link_id = port_info['network_id']
+ if ('device_id' in port_info) and (port_info['device_id']):
+ c_point.vdu_id = port_info['device_id']
+
+ def _fill_virtual_link_info(self, drv, network_info):
+ link = RwcalYang.VirtualLinkInfoParams()
+ link.name = network_info['name']
+ link.virtual_link_id = network_info['id']
+ if network_info['admin_state_up']:
+ link.state = 'active'
+ else:
+ link.state = 'inactive'
+ link.virtual_link_id = network_info['id']
+ if ('provider:physical' in network_info) and (network_info['provider:physical']):
+ link.provider_network.physical_network = network_info['provider:physical']
+ if ('provider:vlan' in network_info) and (network_info['provider:vlan']):
+ link.provider_network.segmentation_id = network_info['provider:vlan']
+ link.provider_network.overlay_type = 'VLAN'
+
+ if 'ports' in network_info:
+ for port in network_info['ports']:
+ if 'port_id' in port:
+ port_id = port['port_id']
+ port = drv.get_port(port_id)
+ c_point = link.connection_points.add()
+ RwcalOpenmanoVimConnector._fill_connection_point_info(c_point, port)
+ return link
+
+ @rwstatus(ret_on_failure=[None])
+ def do_get_virtual_link(self, account, link_id):
+ with self._use_driver(account) as drv:
+ network = drv.get_network(link_id)
+ return self._fill_virtual_link_info(drv,network)
+
+ @rwstatus(ret_on_failure=[""])
+ def do_get_virtual_link_list(self, account):
+ response = RwcalYang.VNFResources()
+ with self._use_driver(account) as drv:
+ networks = drv.get_network_list()
+ for network in networks:
+ network_info = drv.get_network(network['id'])
+ response.virtual_link_info_list.append(self._fill_virtual_link_info(drv,network_info))
+ return response
+
+ def _match_vm_flavor(self, required, available):
+ self.log.info("Matching VM Flavor attributes required {}, available {}".format(required, available))
+ if available.vcpu_count != required.vcpu_count:
+ return False
+ if available.memory_mb != required.memory_mb:
+ return False
+ if available.storage_gb != required.storage_gb:
+ return False
+ self.log.debug("VM Flavor match found")
+ return True
+
+
+ def _select_resource_flavor(self, account, vdu_init):
+ """
+ Select a existing flavor if it matches the request or create new flavor
+ """
+ flavor = RwcalYang.FlavorInfoItem()
+ flavor.name = str(uuid.uuid4())
+ epa_types = ['vm_flavor', 'guest_epa', 'host_epa', 'host_aggregate', 'hypervisor_epa', 'vswitch_epa']
+ epa_dict = {k: v for k, v in vdu_init.as_dict().items() if k in epa_types}
+ flavor.from_dict(epa_dict)
+
+ rc, response = self.do_get_flavor_list(account)
+ if rc != RwTypes.RwStatus.SUCCESS:
+ self.log.error("Get-flavor-info-list operation failed for cloud account: %s",
+ account.name)
+ raise OpenvimCALOperationFailure("Get-flavor-info-list operation failed for cloud account: %s" %(account.name))
+
+ flavor_id = None
+ flavor_list = response.flavorinfo_list
+ self.log.debug("Received %d flavor information from RW.CAL", len(flavor_list))
+ for flv in flavor_list:
+ self.log.info("Attempting to match compute requirement for VDU: %s with flavor %s",
+ vdu_init.name, flv)
+ if self._match_vm_flavor(flavor.vm_flavor,flv.vm_flavor):
+ self.log.info("Flavor match found for compute requirements for VDU: %s with flavor name: %s, flavor-id: %s",
+ vdu_init.name, flv.name, flv.id)
+ return flv.id
+
+ if account.openvim.dynamic_flavor_support is False:
+ self.log.error("Unable to create flavor for compute requirement for VDU: %s. VDU instantiation failed", vdu_init.name)
+ raise OpenvimCALOperationFailure("No resource available with matching EPA attributes")
+ else:
+ rc,flavor_id = self.do_create_flavor(account,flavor)
+ if rc != RwTypes.RwStatus.SUCCESS:
+ self.log.error("Create-flavor operation failed for cloud account: %s",
+ account.name)
+ raise OpenvimCALOperationFailure("Create-flavor operation failed for cloud account: %s" %(account.name))
+ return flavor_id
+
+
+ @rwcalstatus(ret_on_failure=[""])
+ def do_create_vdu(self, account, vdu_init):
+ with self._use_driver(account) as drv:
+ net_list = list()
+
+ if not vdu_init.has_field('flavor_id'):
+ vdu_init.flavor_id = self._select_resource_flavor(account,vdu_init)
+
+ if account.openvim.mgmt_network:
+ mgmt_net_list = drv.get_network_list()
+ mgmt_net_id = [net['id'] for net in mgmt_net_list if net['name'] == account.openvim.mgmt_network]
+ if len(mgmt_net_id) > 0:
+ mgmt_net_dict = {}
+ mgmt_net_dict['name'] = account.openvim.mgmt_network
+ mgmt_net_dict['net_id'] = mgmt_net_id[0]
+ mgmt_net_dict['type'] = 'virtual'
+ net_list.append(mgmt_net_dict)
+
+ for c_point in vdu_init.connection_points:
+ net_dict = {}
+ net_dict['name'] = c_point.name
+ net_dict['net_id'] = c_point.virtual_link_id
+ net_dict['type'] = 'virtual'
+ net_list.append(net_dict)
+
+ vm_id = drv.new_vminstance(vdu_init.name,vdu_init.name,None,vdu_init.image_id,vdu_init.flavor_id,net_list);
+ return vm_id
+
+ @rwstatus
+ def do_modify_vdu(self, account, vdu_modify):
+ pass
+
+ @rwstatus
+ def do_delete_vdu(self, account, vdu_id):
+ if not vdu_id:
+ self.log.error("empty vdu_id during the vdu deletion")
+ return
+
+ with self._use_driver(account) as drv:
+ drv.delete_vminstance(vdu_id)
+
+ @staticmethod
+ def _fill_vdu_info(drv,account,vm_info):
+ vdu = RwcalYang.VDUInfoParams()
+ vdu.name = vm_info['name']
+ vdu.vdu_id = vm_info['id']
+ mgmt_net_id = None
+ if ('image' in vm_info) and ('id' in vm_info['image']):
+ vdu.image_id = vm_info['image']['id']
+ if ('flavor' in vm_info) and ('id' in vm_info['flavor']):
+ vdu.flavor_id = vm_info['flavor']['id']
+ vdu.cloud_type = 'openvim'
+
+ if account.openvim.mgmt_network:
+ net_list = drv.get_network_list()
+ mgmt_net_list = [net['id'] for net in net_list if net['name'] == account.openvim.mgmt_network]
+ if len(mgmt_net_list) > 0:
+ mgmt_net_id = mgmt_net_list[0]
+
+ if 'networks' in vm_info:
+ for network in vm_info['networks']:
+ port_id = network['iface_id']
+ port = drv.get_port(port_id)
+ if 'network_id' in port and mgmt_net_id == port['network_id'] and 'ip_address' in port:
+ vdu.management_ip = port['ip_address']
+ vdu.public_ip = vdu.management_ip
+ else:
+ c_point = vdu.connection_points.add()
+ RwcalOpenmanoVimConnector._fill_connection_point_info(c_point, port)
+
+
+ if vm_info['status'] == 'ACTIVE' and vdu.management_ip != '':
+ vdu.state = 'active'
+ elif vm_info['status'] == 'ERROR':
+ vdu.state = 'failed'
+ else:
+ vdu.state = 'inactive'
+
+ if vdu.flavor_id:
+ flavor = drv.get_flavor(vdu.flavor_id)
+ RwcalOpenmanoVimConnector._fill_epa_attributes(vdu, flavor)
+ return vdu
+
+ @rwstatus(ret_on_failure=[None])
+ def do_get_vdu(self, account, vdu_id):
+ with self._use_driver(account) as drv:
+ vm_info = drv.get_vminstance(vdu_id)
+ return RwcalOpenmanoVimConnector._fill_vdu_info(drv,account,vm_info)
+
+ @rwstatus(ret_on_failure=[""])
+ def do_get_vdu_list(self, account):
+ vnf_resource = RwcalYang.VNFResources()
+ with self._use_driver(account) as drv:
+ vms = drv.get_vminstance_list()
+ for vm in vms:
+ vm_info = drv.get_vminstance(vm['id'])
+ vdu = RwcalOpenmanoVimConnector._fill_vdu_info(drv,account,vm_info)
+ vnf_resource.vdu_info_list.append(vdu)
+ return vnf_resource
+