Merge branch 'py3' features 8029 8030
[osm/RO.git] / RO-VIM-vmware / osm_rovim_vmware / vimconn_vmware.py
index e37c419..171f7d4 100644 (file)
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 
 ##
-# Copyright 2016-2017 VMware Inc.
+# Copyright 2016-2019 VMware Inc.
 # This file is part of ETSI OSM
 # All Rights Reserved.
 #
@@ -57,7 +57,7 @@ import time
 import uuid
 # import httplib
 #For python3
-#import http.client
+#import http.client  # TODO py3 check
 import hashlib
 import socket
 import struct
@@ -446,9 +446,7 @@ class vimconnector(vimconn.vimconnector):
                     raise vimconn.vimconnNotFoundException("Fail to get tenant {}".format(tenant_id))
 
                 lxmlroot_respond = lxmlElementTree.fromstring(response.content)
-                namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
-                #For python3
-                #namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
+                namespaces = {prefix: uri for prefix, uri in lxmlroot_respond.nsmap.items() if prefix}
                 namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
                 vdc_remove_href = lxmlroot_respond.find("xmlns:Link[@rel='remove']",namespaces).attrib['href']
                 vdc_remove_href = vdc_remove_href + '?recursive=true&force=true'
@@ -503,7 +501,7 @@ class vimconnector(vimconn.vimconnector):
 
         return vdclist
 
-    def new_network(self, net_name, net_type, ip_profile=None, shared=False, vlan=None):
+    def new_network(self, net_name, net_type, ip_profile=None, shared=False, provider_network_profile=None):
         """Adds a tenant network to VIM
         Params:
             'net_name': name of the network
@@ -520,7 +518,7 @@ class vimconnector(vimconn.vimconnector):
                 'dhcp_start_address': ip_schema, first IP to grant
                 'dhcp_count': number of IPs to grant.
             'shared': if this network can be seen/use by other tenants/organization
-            'vlan': in case of a data or ptp net_type, the intended vlan tag to be used for the network
+            'provider_network_profile': (optional) contains {segmentation-id: vlan, provider-network: vim_netowrk}
         Returns a tuple with the network identifier and created_items, or raises an exception on error
             created_items can be None or a dictionary where this method can include key-values that will be passed to
             the method delete_network. Can be used to store created segments, created l2gw connections, etc.
@@ -528,8 +526,11 @@ class vimconnector(vimconn.vimconnector):
             as not present.
         """
 
-        self.logger.debug("new_network tenant {} net_type {} ip_profile {} shared {}"
-                          .format(net_name, net_type, ip_profile, shared))
+        self.logger.debug("new_network tenant {} net_type {} ip_profile {} shared {} provider_network_profile {}"
+                          .format(net_name, net_type, ip_profile, shared, provider_network_profile))
+        vlan = None
+        if provider_network_profile:
+            vlan = provider_network_profile.get("segmentation-id")
 
         created_items = {}
         isshared = 'false'
@@ -541,9 +542,19 @@ class vimconnector(vimconn.vimconnector):
 #             if self.config.get('dv_switch_name') == None:
 #                  raise vimconn.vimconnConflictException("You must provide 'dv_switch_name' at config value")
 #             network_uuid = self.create_dvPort_group(net_name)
+        parent_network_uuid = None
+
+        import traceback
+        traceback.print_stack()
+
+        if provider_network_profile is not None:
+            for k, v in provider_network_profile.items():
+                if k == 'physical_network':
+                    parent_network_uuid = self.get_physical_network_by_name(v)
 
         network_uuid = self.create_network(network_name=net_name, net_type=net_type,
-                                           ip_profile=ip_profile, isshared=isshared)
+                                           ip_profile=ip_profile, isshared=isshared,
+                                           parent_network_uuid=parent_network_uuid)
         if network_uuid is not None:
             return network_uuid, created_items
         else:
@@ -976,9 +987,7 @@ class vimconnector(vimconn.vimconnector):
             raise vimconn.vimconnNotFoundException("Fail to get image {}".format(image_id))
 
         lxmlroot_respond = lxmlElementTree.fromstring(response.content)
-        namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
-        #For python3
-        #namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
+        namespaces = {prefix: uri for prefix, uri in lxmlroot_respond.nsmap.items() if prefix}
         namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
 
         catalogItems_section = lxmlroot_respond.find("xmlns:CatalogItems",namespaces)
@@ -999,9 +1008,7 @@ class vimconnector(vimconn.vimconnector):
                                                                                     image_id))
 
             lxmlroot_respond = lxmlElementTree.fromstring(response.content)
-            namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
-            #For python3
-            #namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
+            namespaces = {prefix: uri for prefix, uri in lxmlroot_respond.nsmap.items() if prefix}
             namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
             catalogitem_remove_href = lxmlroot_respond.find("xmlns:Link[@rel='remove']",namespaces).attrib['href']
 
@@ -1409,11 +1416,8 @@ class vimconnector(vimconn.vimconnector):
             return None
         # UUID has following format https://host/api/vApp/vapp-30da58a3-e7c7-4d09-8f68-d4c8201169cf
         try:
-            refs = filter(lambda ref: ref.name == vapp_name and ref.type_ == 'application/vnd.vmware.vcloud.vApp+xml',
-                          vdc.ResourceEntities.ResourceEntity)
-            #For python3
-            #refs = [ref for ref in vdc.ResourceEntities.ResourceEntity\
-            #         if ref.name == vapp_name and ref.type_ == 'application/vnd.vmware.vcloud.vApp+xml']
+            refs = [ref for ref in vdc.ResourceEntities.ResourceEntity \
+                    if ref.name == vapp_name and ref.type_ == 'application/vnd.vmware.vcloud.vApp+xml']
             if len(refs) == 1:
                 return refs[0].href.split("vapp")[1][1:]
         except Exception as e:
@@ -1435,12 +1439,8 @@ class vimconnector(vimconn.vimconnector):
                 :param vapp_uuid:
         """
         try:
-            refs = filter(lambda ref:
-                          ref.type_ == 'application/vnd.vmware.vcloud.vApp+xml',
-                          vdc.ResourceEntities.ResourceEntity)
-            #For python3
-            #refs = [ref for ref in vdc.ResourceEntities.ResourceEntity\
-            #         if ref.type_ == 'application/vnd.vmware.vcloud.vApp+xml']
+            refs = [ref for ref in vdc.ResourceEntities.ResourceEntity\
+                     if ref.type_ == 'application/vnd.vmware.vcloud.vApp+xml']
             for ref in refs:
                 vappid = ref.href.split("vapp")[1][1:]
                 # find vapp with respected vapp uuid
@@ -1926,9 +1926,7 @@ class vimconnector(vimconn.vimconnector):
 
                 if primary_netname is not None:
                     self.logger.debug("new_vminstance(): Filtering by net name {}".format(interface_net_name))
-                    nets = filter(lambda n: n.get('name') == interface_net_name, self.get_network_list())
-                    #For python3
-                    #nets = [n for n in self.get_network_list() if n.get('name') == interface_net_name]
+                    nets = [n for n in self.get_network_list() if n.get('name') == interface_net_name]
                     if len(nets) == 1:
                         self.logger.info("new_vminstance(): Found requested network: {}".format(nets[0].get('name')))
 
@@ -3062,7 +3060,6 @@ class vimconnector(vimconn.vimconnector):
         except XmlElementTree.ParseError as Err:
             self.logger.debug("ParseError in response from NSX Manager {}".format(Err.message), exc_info=True)
 
-
     def action_vminstance(self, vm__vim_uuid=None, action_dict=None, created_items={}):
         """Send and action over a VM instance from VIM
         Returns the vm_id if the action was successfully sent to the VIM"""
@@ -3073,7 +3070,7 @@ class vimconnector(vimconn.vimconnector):
 
         org, vdc = self.get_vdc_details()
         if vdc is None:
-            raise  vimconn.vimconnException("Failed to get a reference of VDC for a tenant {}".format(self.tenant_name))
+            raise vimconn.vimconnException("Failed to get a reference of VDC for a tenant {}".format(self.tenant_name))
 
         vapp_name = self.get_namebyvappid(vm__vim_uuid)
         if vapp_name is None:
@@ -3107,9 +3104,7 @@ class vimconnector(vimconn.vimconnector):
                 result = self.client.get_task_monitor().wait_for_success(task=poweron_task)
                 self.instance_actions_result("resume", result, vapp_name)
             elif "shutoff" in action_dict or "shutdown" in action_dict:
-                action_name , value = action_dict.items()[0]
-                #For python3
-                #action_name , value = list(action_dict.items())[0]
+                action_name , value = list(action_dict.items())[0]
                 self.logger.info("action_vminstance: {} vApp: {}".format(action_name, vapp_name))
                 shutdown_task = vapp.shutdown()
                 result = self.client.get_task_monitor().wait_for_success(task=shutdown_task)
@@ -3285,7 +3280,6 @@ class vimconnector(vimconn.vimconnector):
             The return network uuid.
             network_uuid: network_id
         """
-
         if not network_name:
             self.logger.debug("get_network_id_by_name() : Network name is empty")
             return None
@@ -3294,9 +3288,7 @@ class vimconnector(vimconn.vimconnector):
             org_dict = self.get_org(self.org_uuid)
             if org_dict and 'networks' in org_dict:
                 org_network_dict = org_dict['networks']
-                for net_uuid,net_name in org_network_dict.items():
-                #For python3
-                #for net_uuid,net_name in org_network_dict.items():
+                for net_uuid, net_name in org_network_dict.items():
                     if net_name == network_name:
                         return net_uuid
 
@@ -3305,6 +3297,81 @@ class vimconnector(vimconn.vimconnector):
 
         return None
 
+    def get_physical_network_by_name(self, physical_network_name):
+        '''
+        Methos returns uuid of physical network which passed
+        Args:
+            physical_network_name: physical network name
+        Returns:
+            UUID of physical_network_name
+        '''
+        try:
+            client_as_admin = self.connect_as_admin()
+            if not client_as_admin:
+                raise vimconn.vimconnConnectionException("Failed to connect vCD.")
+            url_list = [self.url, '/api/admin/vdc/', self.tenant_id]
+            vm_list_rest_call = ''.join(url_list)
+
+            if client_as_admin._session:
+                headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+                         'x-vcloud-authorization': client_as_admin._session.headers['x-vcloud-authorization']}
+
+                response = self.perform_request(req_type='GET',
+                                                url=vm_list_rest_call,
+                                                headers=headers)
+
+                provider_network = None
+                available_network = None
+                add_vdc_rest_url = None
+
+                if response.status_code != requests.codes.ok:
+                    self.logger.debug("REST API call {} failed. Return status code {}".format(vm_list_rest_call,
+                                                                                              response.status_code))
+                    return None
+                else:
+                    try:
+                        vm_list_xmlroot = XmlElementTree.fromstring(response.content)
+                        for child in vm_list_xmlroot:
+
+                            if child.tag.split("}")[1] == 'ProviderVdcReference':
+                                provider_network = child.attrib.get('href')
+                                # application/vnd.vmware.admin.providervdc+xml
+                            if child.tag.split("}")[1] == 'Link':
+                                if child.attrib.get('type') == 'application/vnd.vmware.vcloud.orgVdcNetwork+xml' \
+                                        and child.attrib.get('rel') == 'add':
+                                    add_vdc_rest_url = child.attrib.get('href')
+                    except:
+                        self.logger.debug("Failed parse respond for rest api call {}".format(vm_list_rest_call))
+                        self.logger.debug("Respond body {}".format(response.content))
+                        return None
+
+                # find  pvdc provided available network
+                response = self.perform_request(req_type='GET',
+                                                url=provider_network,
+                                                headers=headers)
+
+                if response.status_code != requests.codes.ok:
+                    self.logger.debug("REST API call {} failed. Return status code {}".format(vm_list_rest_call,
+                                                                                              response.status_code))
+                    return None
+
+                try:
+                    vm_list_xmlroot = XmlElementTree.fromstring(response.content)
+                    for child in vm_list_xmlroot.iter():
+                        if child.tag.split("}")[1] == 'AvailableNetworks':
+                            for networks in child.iter():
+                                if networks.attrib.get('href') is not None and networks.attrib.get('name') is not None:
+                                    if networks.attrib.get('name') == physical_network_name:
+                                        network_url = networks.attrib.get('href')
+                                        available_network = network_url[network_url.rindex('/')+1:]
+                                        break
+                except Exception as e:
+                    return None
+
+            return available_network
+        except Exception as e:
+            self.logger.error("Error while getting physical network: {}".format(e))
+
     def list_org_action(self):
         """
         Method leverages vCloud director and query for available organization for particular user
@@ -3451,11 +3518,8 @@ class vimconnector(vimconn.vimconnector):
         vm_list_rest_call = ''.join(url_list)
 
         if not (not vca.vcloud_session or not vca.vcloud_session.organization):
-            refs = filter(lambda ref: ref.name == vdc_name and ref.type_ == 'application/vnd.vmware.vcloud.vdc+xml',
-                          vca.vcloud_session.organization.Link)
-            #For python3
-            #refs = [ref for ref in vca.vcloud_session.organization.Link if ref.name == vdc_name and\
-            #        ref.type_ == 'application/vnd.vmware.vcloud.vdc+xml']
+            refs = [ref for ref in vca.vcloud_session.organization.Link if ref.name == vdc_name and
+                    ref.type_ == 'application/vnd.vmware.vcloud.vdc+xml']
             if len(refs) == 1:
                 response = Http.get(url=vm_list_rest_call,
                                     headers=vca.vcloud_session.get_vcloud_headers(),
@@ -3789,6 +3853,7 @@ class vimconnector(vimconn.vimconnector):
                 try:
                     vm_list_xmlroot = XmlElementTree.fromstring(response.content)
                     for child in vm_list_xmlroot:
+
                         if child.tag.split("}")[1] == 'ProviderVdcReference':
                             provider_network = child.attrib.get('href')
                             # application/vnd.vmware.admin.providervdc+xml
@@ -3805,6 +3870,7 @@ class vimconnector(vimconn.vimconnector):
             response = self.perform_request(req_type='GET',
                                             url=provider_network,
                                             headers=headers)
+
             if response.status_code != requests.codes.ok:
                 self.logger.debug("REST API call {} failed. Return status code {}".format(vm_list_rest_call,
                                                                                           response.status_code))
@@ -3890,31 +3956,61 @@ class vimconnector(vimconn.vimconnector):
             dns2_text = ""
             if len(dns_list) >= 2:
                 dns2_text = "\n                                                <Dns2>{}</Dns2>\n".format(dns_list[1])
-            data = """ <OrgVdcNetwork name="{0:s}" xmlns="http://www.vmware.com/vcloud/v1.5">
-                            <Description>Openmano created</Description>
-                                    <Configuration>
-                                        <IpScopes>
-                                            <IpScope>
-                                                <IsInherited>{1:s}</IsInherited>
-                                                <Gateway>{2:s}</Gateway>
-                                                <Netmask>{3:s}</Netmask>
-                                                <Dns1>{4:s}</Dns1>{5:s}
-                                                <IsEnabled>{6:s}</IsEnabled>
-                                                <IpRanges>
-                                                    <IpRange>
-                                                        <StartAddress>{7:s}</StartAddress>
-                                                        <EndAddress>{8:s}</EndAddress>
-                                                    </IpRange>
-                                                </IpRanges>
-                                            </IpScope>
-                                        </IpScopes>
-                                        <FenceMode>{9:s}</FenceMode>
-                                    </Configuration>
-                                    <IsShared>{10:s}</IsShared>
-                        </OrgVdcNetwork> """.format(escape(network_name), is_inherited, gateway_address,
-                                                    subnet_address, dns1, dns2_text, dhcp_enabled,
-                                                    dhcp_start_address, dhcp_end_address,
-                                                    fence_mode, isshared)
+            if net_type == "isolated":
+                fence_mode="isolated"
+                data = """ <OrgVdcNetwork name="{0:s}" xmlns="http://www.vmware.com/vcloud/v1.5">
+                                <Description>Openmano created</Description>
+                                        <Configuration>
+                                            <IpScopes>
+                                                <IpScope>
+                                                    <IsInherited>{1:s}</IsInherited>
+                                                    <Gateway>{2:s}</Gateway>
+                                                    <Netmask>{3:s}</Netmask>
+                                                    <Dns1>{4:s}</Dns1>{5:s}
+                                                    <IsEnabled>{6:s}</IsEnabled>
+                                                    <IpRanges>
+                                                        <IpRange>
+                                                            <StartAddress>{7:s}</StartAddress>
+                                                            <EndAddress>{8:s}</EndAddress>
+                                                        </IpRange>
+                                                    </IpRanges>
+                                                </IpScope>
+                                            </IpScopes>
+                                            <FenceMode>{9:s}</FenceMode>
+                                        </Configuration>
+                                        <IsShared>{10:s}</IsShared>
+                            </OrgVdcNetwork> """.format(escape(network_name), is_inherited, gateway_address,
+                                                        subnet_address, dns1, dns2_text, dhcp_enabled,
+                                                        dhcp_start_address, dhcp_end_address,
+                                                        fence_mode, isshared)
+            else:
+                fence_mode = "bridged"
+                data = """ <OrgVdcNetwork name="{0:s}" xmlns="http://www.vmware.com/vcloud/v1.5">
+                        <Description>Openmano created</Description>
+                                <Configuration>
+                                    <IpScopes>
+                                        <IpScope>
+                                            <IsInherited>{1:s}</IsInherited>
+                                            <Gateway>{2:s}</Gateway>
+                                            <Netmask>{3:s}</Netmask>
+                                            <Dns1>{4:s}</Dns1>{5:s}
+                                            <IsEnabled>{6:s}</IsEnabled>
+                                            <IpRanges>
+                                                <IpRange>
+                                                    <StartAddress>{7:s}</StartAddress>
+                                                    <EndAddress>{8:s}</EndAddress>
+                                                </IpRange>
+                                            </IpRanges>
+                                        </IpScope>
+                                    </IpScopes>
+                                    <ParentNetwork href="{9:s}"/>
+                                    <FenceMode>{10:s}</FenceMode>
+                                </Configuration>
+                                <IsShared>{11:s}</IsShared>
+                    </OrgVdcNetwork> """.format(escape(network_name), is_inherited, gateway_address,
+                                                subnet_address, dns1, dns2_text, dhcp_enabled,
+                                                dhcp_start_address, dhcp_end_address, available_networks,
+                                                fence_mode, isshared)
 
             headers['Content-Type'] = 'application/vnd.vmware.vcloud.orgVdcNetwork+xml'
             try:
@@ -4399,9 +4495,7 @@ class vimconnector(vimconn.vimconnector):
             return None
         try:
             lxmlroot_respond = lxmlElementTree.fromstring(response.content)
-            namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
-            #For python3
-            #namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
+            namespaces = {prefix: uri for prefix, uri in lxmlroot_respond.nsmap.items() if prefix}
             namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
 
             for item in lxmlroot_respond.iterfind('xmlns:Item',namespaces):
@@ -5538,9 +5632,7 @@ class vimconnector(vimconn.vimconnector):
         try:
             #Find but type & max of instance IDs assigned to disks
             lxmlroot_respond = lxmlElementTree.fromstring(response.content)
-            namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
-            #For python3
-            #namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
+            namespaces = {prefix: uri for prefix, uri in lxmlroot_respond.nsmap.items() if prefix}
             namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
             instance_id = 0
             for item in lxmlroot_respond.iterfind('xmlns:Item',namespaces):
@@ -6278,14 +6370,12 @@ class vimconnector(vimconn.vimconnector):
             used_ids = list(self.persistent_info["used_vlanIDs"].values())
 
         for vlanID_range in self.config.get('vlanID_range'):
-            start_vlanid , end_vlanid = vlanID_range.split("-")
+            start_vlanid, end_vlanid = vlanID_range.split("-")
             if start_vlanid > end_vlanid:
                 raise vimconn.vimconnConflictException("Invalid vlan ID range {}".format(
                                                                         vlanID_range))
 
-            for id in xrange(int(start_vlanid), int(end_vlanid) + 1):
-            #For python3
-            #for id in range(int(start_vlanid), int(end_vlanid) + 1):
+            for id in range(int(start_vlanid), int(end_vlanid) + 1):
                 if id not in used_ids:
                     vlan_id = id
                     self.persistent_info["used_vlanIDs"][network_name] = vlan_id