RIFT OSM R1 Initial Submission
[osm/SO.git] / rwcal / plugins / vala / rwcal_openmano_vimconnector / rwcal_openmano_vimconnector.py
diff --git a/rwcal/plugins/vala/rwcal_openmano_vimconnector/rwcal_openmano_vimconnector.py b/rwcal/plugins/vala/rwcal_openmano_vimconnector/rwcal_openmano_vimconnector.py
new file mode 100644 (file)
index 0000000..aa3d971
--- /dev/null
@@ -0,0 +1,664 @@
+
+# 
+#   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
+