Bug 573 VCD: Ensure that more than 2 NICs can get connected to VCD VM 67/6767/1
authorRavi Chamarty <ravi.chamarty@riftio.com>
Fri, 26 Oct 2018 01:40:50 +0000 (01:40 +0000)
committerRavi Chamarty <ravi.chamarty@riftio.com>
Fri, 26 Oct 2018 01:41:18 +0000 (01:41 +0000)
Ensure REST API calls for NetworkConfigSection and NetworkConnectionSection use native REST rather than pyvcloud

Signed-off-by: Ravi Chamarty <ravi.chamarty@riftio.com>
osm_ro/vimconn_vmware.py

index c0d7f02..00ecddd 100644 (file)
@@ -1869,6 +1869,7 @@ class vimconnector(vimconn.vimconnector):
             vdc_obj = VDC(self.client, href=vdc.get('href'))
             vapp_resource = vdc_obj.get_vapp(vmname_andid)
             vapp = VApp(self.client, resource=vapp_resource)
+            vapp_id = vapp_resource.get('id').split(':')[-1]
 
             self.logger.info("Removing primary NIC: ")
             # First remove all NICs so that NIC properties can be adjusted as needed
@@ -1913,8 +1914,7 @@ class vimconnector(vimconn.vimconnector):
                         if interface_net_name != primary_netname:
                             # connect network to VM - with all DHCP by default
                             self.logger.info("new_vminstance(): Attaching net {} to vapp".format(interface_net_name))
-                            task = vapp.connect_org_vdc_network(nets[0].get('name'))
-                            self.client.get_task_monitor().wait_for_success(task=task)
+                            self.connect_vapp_to_org_vdc_network(vapp_id, nets[0].get('name'))
 
                         type_list = ('PF', 'PCI-PASSTHROUGH', 'VFnotShared')
                         if 'type' in net and net['type'] not in type_list:
@@ -1951,7 +1951,6 @@ class vimconnector(vimconn.vimconnector):
 
             self.logger.debug("new_vminstance(): starting power on vApp {} ".format(vmname_andid))
 
-            vapp_id = vapp_resource.get('id').split(':')[-1]
             poweron_task = self.power_on_vapp(vapp_id, vmname_andid)
             result = self.client.get_task_monitor().wait_for_success(task=poweron_task)
             if result.get('status') == 'success':
@@ -3680,9 +3679,16 @@ class vimconnector(vimconn.vimconnector):
             # either use client provided UUID or search for a first available
             #  if both are not defined we return none
             if parent_network_uuid is not None:
-                url_list = [self.url, '/api/admin/network/', parent_network_uuid]
+                provider_network = None
+                available_networks = None
+                add_vdc_rest_url = None
+
+                url_list = [self.url, '/api/admin/vdc/', self.tenant_id, '/networks']
                 add_vdc_rest_url = ''.join(url_list)
 
+                url_list = [self.url, '/api/admin/network/', parent_network_uuid]
+                available_networks = ''.join(url_list)
+
             #Creating all networks as Direct Org VDC type networks.
             #Unused in case of Underlay (data/ptp) network interface.
             fence_mode="bridged"
@@ -4682,6 +4688,89 @@ class vimconnector(vimconn.vimconnector):
                     self.logger.error("reserve_memory_for_all_vms(): VM {} failed "\
                                       .format(vm_id))
 
+    def connect_vapp_to_org_vdc_network(self, vapp_id, net_name):
+        """
+            Configure VApp network config with org vdc network
+            Args :
+                vapp - VApp
+            Returns:
+                None
+        """
+
+        self.logger.info("Connecting vapp {} to org vdc network {}".
+                         format(vapp_id, net_name))
+
+        url_rest_call = "{}/api/vApp/vapp-{}/networkConfigSection/".format(self.url, vapp_id)
+
+        headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+                   'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+        response = self.perform_request(req_type='GET',
+                                        url=url_rest_call,
+                                        headers=headers)
+
+        if response.status_code == 403:
+            response = self.retry_rest('GET', url_rest_call)
+
+        if response.status_code != 200:
+            self.logger.error("REST call {} failed reason : {}"\
+                              "status code : {}".format(url_rest_call,
+                                                        response.content,
+                                                        response.status_code))
+            raise vimconn.vimconnException("connect_vapp_to_org_vdc_network : Failed to get "\
+                                           "network config section")
+
+        data = response.content
+        headers['Content-Type'] = 'application/vnd.vmware.vcloud.networkConfigSection+xml'
+        net_id = self.get_network_id_by_name(net_name)
+        if not net_id:
+            raise vimconn.vimconnException("connect_vapp_to_org_vdc_network : Failed to find "\
+                                           "existing network")
+
+        bytexml = bytes(bytearray(data, encoding='utf-8'))
+        newelem = lxmlElementTree.XML(bytexml)
+        namespaces = {prefix: uri for prefix, uri in newelem.nsmap.iteritems() if prefix}
+        namespaces["xmlns"] = "http://www.vmware.com/vcloud/v1.5"
+        nwcfglist = newelem.findall(".//xmlns:NetworkConfig", namespaces)
+
+        newstr = """<NetworkConfig networkName="{}">
+                  <Configuration>
+                       <ParentNetwork href="{}/api/network/{}"/>
+                       <FenceMode>bridged</FenceMode>
+                  </Configuration>
+              </NetworkConfig>
+           """.format(net_name, self.url, net_id)
+        newcfgelem = lxmlElementTree.fromstring(newstr)
+        if nwcfglist:
+            nwcfglist[0].addnext(newcfgelem)
+
+        newdata = lxmlElementTree.tostring(newelem, pretty_print=True)
+
+        response = self.perform_request(req_type='PUT',
+                                        url=url_rest_call,
+                                        headers=headers,
+                                        data=newdata)
+
+        if response.status_code == 403:
+            add_headers = {'Content-Type': headers['Content-Type']}
+            response = self.retry_rest('PUT', url_rest_call, add_headers, newdata)
+
+        if response.status_code != 202:
+            self.logger.error("REST call {} failed reason : {}"\
+                              "status code : {} ".format(url_rest_call,
+                              response.content,
+                              response.status_code))
+            raise vimconn.vimconnException("connect_vapp_to_org_vdc_network : Failed to update "\
+                                           "network config section")
+        else:
+            vapp_task = self.get_task_from_response(response.content)
+            result = self.client.get_task_monitor().wait_for_success(task=vapp_task)
+            if result.get('status') == 'success':
+                self.logger.info("connect_vapp_to_org_vdc_network(): Vapp {} connected to "\
+                                 "network {}".format(vapp_id, net_name))
+            else:
+                self.logger.error("connect_vapp_to_org_vdc_network(): Vapp {} failed to "\
+                                  "connect to network {}".format(vapp_id, net_name))
+
     def remove_primary_network_adapter_from_all_vms(self, vapp):
         """
             Method to remove network adapter type to vm