Add device role tagging functionality to openstack connector. All interfaces are...
[osm/RO.git] / osm_ro / vimconn_openstack.py
index cc15ef6..7e64012 100644 (file)
@@ -64,7 +64,7 @@ netStatus2manoFormat={'ACTIVE':'ACTIVE','PAUSED':'PAUSED','INACTIVE':'INACTIVE',
 
 #global var to have a timeout creating and deleting volumes
 volume_timeout = 60
-server_timeout = 60
+server_timeout = 300
 
 class vimconnector(vimconn.vimconnector):
     def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None,
@@ -89,6 +89,7 @@ class vimconnector(vimconn.vimconnector):
         self.neutron = self.session.get('neutron')
         self.cinder = self.session.get('cinder')
         self.glance = self.session.get('glance')
+        self.glancev1 = self.session.get('glancev1')
         self.keystone = self.session.get('keystone')
         self.api_version3 = self.session.get('api_version3')
 
@@ -148,10 +149,20 @@ class vimconnector(vimconn.vimconnector):
             else:
                 self.keystone = ksClient_v2.Client(session=sess)
             self.session['keystone'] = self.keystone
-            self.nova = self.session['nova'] = nClient.Client("2.1", session=sess)
+            # In order to enable microversion functionality an explicit microversion must be specified in 'config'.
+            # This implementation approach is due to the warning message in
+            # https://developer.openstack.org/api-guide/compute/microversions.html
+            # where it is stated that microversion backwards compatibility is not guaranteed and clients should
+            # always require an specific microversion.
+            # To be able to use 'device role tagging' functionality define 'microversion: 2.32' in datacenter config
+            version = self.config.get("microversion")
+            if not version:
+                version = "2.1"
+            self.nova = self.session['nova'] = nClient.Client(str(version), session=sess)
             self.neutron = self.session['neutron'] = neClient.Client('2.0', session=sess)
             self.cinder = self.session['cinder'] = cClient.Client(2, session=sess)
             self.glance = self.session['glance'] = glClient.Client(2, session=sess)
+            self.glancev1 = self.session['glancev1'] = glClient.Client('1', session=sess)
             self.session['reload_client'] = False
             self.persistent_info['session'] = self.session
 
@@ -186,6 +197,7 @@ class vimconnector(vimconn.vimconnector):
         elif isinstance(exception, vimconn.vimconnException):
             raise
         else:  # ()
+            self.logger.error("General Exception " + str(exception), exc_info=True)
             raise vimconn.vimconnConnectionException(type(exception).__name__ + ": " + str(exception))
 
     def get_tenant_list(self, filter_dict={}):
@@ -563,9 +575,6 @@ class vimconnector(vimconn.vimconnector):
             metadata: metadata of the image
         Returns the image_id
         '''
-        # ALF TODO: revise and change for the new method or session
-        #using version 1 of glance client
-        glancev1 = gl1Client.Client('1',self.glance_endpoint, token=self.keystone.auth_token, **self.k_creds)  #TODO check k_creds vs n_creds
         retry=0
         max_retries=3
         while retry<max_retries:
@@ -596,11 +605,11 @@ class vimconnector(vimconn.vimconnector):
                         disk_format="raw"
                 self.logger.debug("new_image: '%s' loading from '%s'", image_dict['name'], image_dict['location'])
                 if image_dict['location'][0:4]=="http":
-                    new_image = glancev1.images.create(name=image_dict['name'], is_public=image_dict.get('public',"yes")=="yes",
+                    new_image = self.glancev1.images.create(name=image_dict['name'], is_public=image_dict.get('public',"yes")=="yes",
                             container_format="bare", location=image_dict['location'], disk_format=disk_format)
                 else: #local path
                     with open(image_dict['location']) as fimage:
-                        new_image = glancev1.images.create(name=image_dict['name'], is_public=image_dict.get('public',"yes")=="yes",
+                        new_image = self.glancev1.images.create(name=image_dict['name'], is_public=image_dict.get('public',"yes")=="yes",
                             container_format="bare", data=fimage, disk_format=disk_format)
                 #insert metadata. We cannot use 'new_image.properties.setdefault' 
                 #because nova and glance are "INDEPENDENT" and we are using nova for reading metadata
@@ -718,6 +727,7 @@ class vimconnector(vimconn.vimconnector):
             no_secured_ports = []   # List of port-is with port-security disabled
             self._reload_connection()
             metadata_vpci={}   # For a specific neutron plugin
+            block_device_mapping = None
             for net in net_list:
                 if not net.get("net_id"): #skip non connected iface
                     continue
@@ -749,8 +759,13 @@ class vimconnector(vimconn.vimconnector):
                 new_port = self.neutron.create_port({"port": port_dict })
                 net["mac_adress"] = new_port["port"]["mac_address"]
                 net["vim_id"] = new_port["port"]["id"]
-                net["ip"] = new_port["port"].get("fixed_ips", [{}])[0].get("ip_address")
-                net_list_vim.append({"port-id": new_port["port"]["id"]})
+                # if try to use a network without subnetwork, it will return a emtpy list
+                fixed_ips = new_port["port"].get("fixed_ips")
+                if fixed_ips:
+                    net["ip"] = fixed_ips[0].get("ip_address")
+                else:
+                    net["ip"] = None
+                net_list_vim.append({"port-id": new_port["port"]["id"], "tag": new_port["port"]["name"]})
 
                 if net.get('floating_ip', False):
                     net['exit_on_floating_ip_error'] = True
@@ -829,10 +844,9 @@ class vimconnector(vimconn.vimconnector):
                 userdata = cloud_config
 
             #Create additional volumes in case these are present in disk_list
-            block_device_mapping = None
             base_disk_index = ord('b')
             if disk_list != None:
-                block_device_mapping = dict()
+                block_device_mapping = {}
                 for disk in disk_list:
                     if 'image_id' in disk:
                         volume = self.cinder.volumes.create(size = disk['size'],name = name + '_vd' +
@@ -879,8 +893,8 @@ class vimconnector(vimconn.vimconnector):
                                               availability_zone=self.config.get('availability_zone'),
                                               key_name=self.config.get('keypair'),
                                               userdata=userdata,
-                                              config_drive = config_drive,
-                                              block_device_mapping = block_device_mapping
+                                              config_drive=config_drive,
+                                              block_device_mapping=block_device_mapping
                                               )  # , description=description)
 
             # Previously mentioned workaround to wait until the VM is active and then disable the port-security
@@ -959,7 +973,7 @@ class vimconnector(vimconn.vimconnector):
 
         except Exception as e:
             # delete the volumes we just created
-            if block_device_mapping != None:
+            if block_device_mapping:
                 for volume_id in block_device_mapping.itervalues():
                     self.cinder.volumes.delete(volume_id)