minor updates to test/basictest.sh
[osm/RO.git] / vimconn_openstack.py
index 70f8c01..81c6591 100644 (file)
@@ -24,8 +24,8 @@
 '''
 osconnector implements all the methods to interact with openstack using the python-client.
 '''
 '''
 osconnector implements all the methods to interact with openstack using the python-client.
 '''
-__author__="Alfonso Tierno, Gerardo Garcia"
-__date__ ="$22-jun-2014 11:19:29$"
+__author__="Alfonso Tierno, Gerardo Garcia, xFlow Research"
+__date__ ="$24-nov-2016 09:10$"
 
 import vimconn
 import json
 
 import vimconn
 import json
@@ -33,14 +33,17 @@ import yaml
 import logging
 import netaddr
 
 import logging
 import netaddr
 
-from novaclient import client as nClient, exceptions as nvExceptions
-import keystoneclient.v2_0.client as ksClient
+from novaclient import client as nClient_v2, exceptions as nvExceptions, api_versions as APIVersion
+import keystoneclient.v2_0.client as ksClient_v2
+from novaclient.v2.client import Client as nClient
+import keystoneclient.v3.client as ksClient
 import keystoneclient.exceptions as ksExceptions
 import glanceclient.v2.client as glClient
 import glanceclient.client as gl1Client
 import glanceclient.exc as gl1Exceptions
 from httplib import HTTPException
 import keystoneclient.exceptions as ksExceptions
 import glanceclient.v2.client as glClient
 import glanceclient.client as gl1Client
 import glanceclient.exc as gl1Exceptions
 from httplib import HTTPException
-from neutronclient.neutron import client as neClient
+from neutronclient.neutron import client as neClient_v2
+from neutronclient.v2_0 import client as neClient
 from neutronclient.common import exceptions as neExceptions
 from requests.exceptions import ConnectionError
 
 from neutronclient.common import exceptions as neExceptions
 from requests.exceptions import ConnectionError
 
@@ -56,11 +59,14 @@ netStatus2manoFormat={'ACTIVE':'ACTIVE','PAUSED':'PAUSED','INACTIVE':'INACTIVE',
                      }
 
 class vimconnector(vimconn.vimconnector):
                      }
 
 class vimconnector(vimconn.vimconnector):
-    def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level="DEBUG", config={}):
+    def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None, config={}):
         '''using common constructor parameters. In this case 
         'url' is the keystone authorization url,
         'url_admin' is not use
         '''
         '''using common constructor parameters. In this case 
         'url' is the keystone authorization url,
         'url_admin' is not use
         '''
+        self.osc_api_version = 'v2.0'
+        if config.get('APIversion') == 'v3.3':
+            self.osc_api_version = 'v3.3'
         vimconn.vimconnector.__init__(self, uuid, name, tenant_id, tenant_name, url, url_admin, user, passwd, log_level, config)
         
         self.k_creds={}
         vimconn.vimconnector.__init__(self, uuid, name, tenant_id, tenant_name, url, url_admin, user, passwd, log_level, config)
         
         self.k_creds={}
@@ -81,8 +87,13 @@ class vimconnector(vimconn.vimconnector):
         if passwd:
             self.k_creds['password'] = passwd
             self.n_creds['api_key']  = passwd
         if passwd:
             self.k_creds['password'] = passwd
             self.n_creds['api_key']  = passwd
+        if self.osc_api_version == 'v3.3':
+            self.k_creds['project_name'] = tenant_name
+            self.k_creds['project_id'] = tenant_id
         self.reload_client       = True
         self.logger = logging.getLogger('openmano.vim.openstack')
         self.reload_client       = True
         self.logger = logging.getLogger('openmano.vim.openstack')
+        if log_level:
+            self.logger.setLevel( getattr(logging, log_level) )
     
     def __setitem__(self,index, value):
         '''Set individuals parameters 
     
     def __setitem__(self,index, value):
         '''Set individuals parameters 
@@ -91,21 +102,37 @@ class vimconnector(vimconn.vimconnector):
         if index=='tenant_id':
             self.reload_client=True
             self.tenant_id = value
         if index=='tenant_id':
             self.reload_client=True
             self.tenant_id = value
-            if value:
-                self.k_creds['tenant_id'] = value
-                self.n_creds['tenant_id']  = value
+            if self.osc_api_version == 'v3.3':
+                if value:
+                    self.k_creds['project_id'] = value
+                    self.n_creds['project_id']  = value
+                else:
+                    del self.k_creds['project_id']
+                    del self.n_creds['project_id']
             else:
             else:
-                del self.k_creds['tenant_name']
-                del self.n_creds['project_id']
+                if value:
+                    self.k_creds['tenant_id'] = value
+                    self.n_creds['tenant_id']  = value
+                else:
+                    del self.k_creds['tenant_id']
+                    del self.n_creds['tenant_id']
         elif index=='tenant_name':
             self.reload_client=True
             self.tenant_name = value
         elif index=='tenant_name':
             self.reload_client=True
             self.tenant_name = value
-            if value:
-                self.k_creds['tenant_name'] = value
-                self.n_creds['project_id']  = value
+            if self.osc_api_version == 'v3.3':
+                if value:
+                    self.k_creds['project_name'] = value
+                    self.n_creds['project_name']  = value
+                else:
+                    del self.k_creds['project_name']
+                    del self.n_creds['project_name']
             else:
             else:
-                del self.k_creds['tenant_name']
-                del self.n_creds['project_id']
+                if value:
+                    self.k_creds['tenant_name'] = value
+                    self.n_creds['project_id']  = value
+                else:
+                    del self.k_creds['tenant_name']
+                    del self.n_creds['project_id']
         elif index=='user':
             self.reload_client=True
             self.user = value
         elif index=='user':
             self.reload_client=True
             self.user = value
@@ -144,14 +171,20 @@ class vimconnector(vimconn.vimconnector):
             #test valid params
             if len(self.n_creds) <4:
                 raise ksExceptions.ClientException("Not enough parameters to connect to openstack")
             #test valid params
             if len(self.n_creds) <4:
                 raise ksExceptions.ClientException("Not enough parameters to connect to openstack")
-            self.nova = nClient.Client(2, **self.n_creds)
-            self.keystone = ksClient.Client(**self.k_creds)
+            if self.osc_api_version == 'v3.3':
+                self.nova = nClient(APIVersion(version_str='2'), **self.n_creds)
+                self.keystone = ksClient.Client(**self.k_creds)
+                self.ne_endpoint=self.keystone.service_catalog.url_for(service_type='network', endpoint_type='publicURL')
+                self.neutron = neClient.Client(APIVersion(version_str='2'), endpoint_url=self.ne_endpoint, token=self.keystone.auth_token, **self.k_creds)
+            else:
+                self.nova = nClient_v2.Client('2', **self.n_creds)
+                self.keystone = ksClient_v2.Client(**self.k_creds)
+                self.ne_endpoint=self.keystone.service_catalog.url_for(service_type='network', endpoint_type='publicURL')
+                self.neutron = neClient_v2.Client('2.0', endpoint_url=self.ne_endpoint, token=self.keystone.auth_token, **self.k_creds)
             self.glance_endpoint = self.keystone.service_catalog.url_for(service_type='image', endpoint_type='publicURL')
             self.glance = glClient.Client(self.glance_endpoint, token=self.keystone.auth_token, **self.k_creds)  #TODO check k_creds vs n_creds
             self.glance_endpoint = self.keystone.service_catalog.url_for(service_type='image', endpoint_type='publicURL')
             self.glance = glClient.Client(self.glance_endpoint, token=self.keystone.auth_token, **self.k_creds)  #TODO check k_creds vs n_creds
-            self.ne_endpoint=self.keystone.service_catalog.url_for(service_type='network', endpoint_type='publicURL')
-            self.neutron = neClient.Client('2.0', endpoint_url=self.ne_endpoint, token=self.keystone.auth_token, **self.k_creds)
             self.reload_client = False
             self.reload_client = False
-        
+
     def __net_os2mano(self, net_list_dict):
         '''Transform the net openstack format to mano format
         net_list_dict can be a list of dict or a single dict'''
     def __net_os2mano(self, net_list_dict):
         '''Transform the net openstack format to mano format
         net_list_dict can be a list of dict or a single dict'''
@@ -193,14 +226,17 @@ class vimconnector(vimconn.vimconnector):
             <other VIM specific>
         Returns the tenant list of dictionaries: [{'name':'<name>, 'id':'<id>, ...}, ...]
         '''
             <other VIM specific>
         Returns the tenant list of dictionaries: [{'name':'<name>, 'id':'<id>, ...}, ...]
         '''
-        self.logger.debug("Getting tenant from VIM filter: '%s'", str(filter_dict))
+        self.logger.debug("Getting tenants from VIM filter: '%s'", str(filter_dict))
         try:
             self._reload_connection()
         try:
             self._reload_connection()
-            tenant_class_list=self.keystone.tenants.findall(**filter_dict)
-            tenant_list=[]
-            for tenant in tenant_class_list:
-                tenant_list.append(tenant.to_dict())
-            return tenant_list
+            if osc_api_version == 'v3.3':
+                project_class_list=self.keystone.projects.findall(**filter_dict)
+            else:
+                project_class_list=self.keystone.tenants.findall(**filter_dict)
+            project_list=[]
+            for project in project_class_list:
+                project_list.append(project.to_dict())
+            return project_list
         except (ksExceptions.ConnectionError, ksExceptions.ClientException, ConnectionError)  as e:
             self._format_exception(e)
 
         except (ksExceptions.ConnectionError, ksExceptions.ClientException, ConnectionError)  as e:
             self._format_exception(e)
 
@@ -209,8 +245,11 @@ class vimconnector(vimconn.vimconnector):
         self.logger.debug("Adding a new tenant name: %s", tenant_name)
         try:
             self._reload_connection()
         self.logger.debug("Adding a new tenant name: %s", tenant_name)
         try:
             self._reload_connection()
-            tenant=self.keystone.tenants.create(tenant_name, tenant_description)
-            return tenant.id
+            if self.osc_api_version == 'v3.3':
+                project=self.keystone.projects.create(tenant_name, tenant_description)
+            else:
+                project=self.keystone.tenants.create(tenant_name, tenant_description)
+            return project.id
         except (ksExceptions.ConnectionError, ksExceptions.ClientException, ConnectionError)  as e:
             self._format_exception(e)
 
         except (ksExceptions.ConnectionError, ksExceptions.ClientException, ConnectionError)  as e:
             self._format_exception(e)
 
@@ -219,15 +258,20 @@ class vimconnector(vimconn.vimconnector):
         self.logger.debug("Deleting tenant %s from VIM", tenant_id)
         try:
             self._reload_connection()
         self.logger.debug("Deleting tenant %s from VIM", tenant_id)
         try:
             self._reload_connection()
-            self.keystone.tenants.delete(tenant_id)
+            if osc_api_version == 'v3.3':
+                self.keystone.projects.delete(tenant_id)
+            else:
+                self.keystone.tenants.delete(tenant_id)
             return tenant_id
         except (ksExceptions.ConnectionError, ksExceptions.ClientException, ConnectionError)  as e:
             self._format_exception(e)
             return tenant_id
         except (ksExceptions.ConnectionError, ksExceptions.ClientException, ConnectionError)  as e:
             self._format_exception(e)
-        
+
     def new_network(self,net_name, net_type, ip_profile=None, shared=False, vlan=None):
         '''Adds a tenant network to VIM. Returns the network identifier'''
         self.logger.debug("Adding a new network to VIM name '%s', type '%s'", net_name, net_type)
     def new_network(self,net_name, net_type, ip_profile=None, shared=False, vlan=None):
         '''Adds a tenant network to VIM. Returns the network identifier'''
         self.logger.debug("Adding a new network to VIM name '%s', type '%s'", net_name, net_type)
+        #self.logger.debug(">>>>>>>>>>>>>>>>>> IP profile %s", str(ip_profile))
         try:
         try:
+            new_net = None
             self._reload_connection()
             network_dict = {'name': net_name, 'admin_state_up': True}
             if net_type=="data" or net_type=="ptp":
             self._reload_connection()
             network_dict = {'name': net_name, 'admin_state_up': True}
             if net_type=="data" or net_type=="ptp":
@@ -255,7 +299,7 @@ class vimconnector(vimconn.vimconnector):
                     }
             if 'gateway_address' in ip_profile:
                 subnet['gateway_ip'] = ip_profile['gateway_address']
                     }
             if 'gateway_address' in ip_profile:
                 subnet['gateway_ip'] = ip_profile['gateway_address']
-            if 'dns_address' in ip_profile:
+            if ip_profile.get('dns_address'):
                 #TODO: manage dns_address as a list of addresses separated by commas 
                 subnet['dns_nameservers'] = []
                 subnet['dns_nameservers'].append(ip_profile['dns_address'])
                 #TODO: manage dns_address as a list of addresses separated by commas 
                 subnet['dns_nameservers'] = []
                 subnet['dns_nameservers'].append(ip_profile['dns_address'])
@@ -269,12 +313,15 @@ class vimconnector(vimconn.vimconnector):
                 #parts = ip_profile['dhcp_start_address'].split('.')
                 #ip_int = (int(parts[0]) << 24) + (int(parts[1]) << 16) + (int(parts[2]) << 8) + int(parts[3])
                 ip_int = int(netaddr.IPAddress(ip_profile['dhcp_start_address']))
                 #parts = ip_profile['dhcp_start_address'].split('.')
                 #ip_int = (int(parts[0]) << 24) + (int(parts[1]) << 16) + (int(parts[2]) << 8) + int(parts[3])
                 ip_int = int(netaddr.IPAddress(ip_profile['dhcp_start_address']))
-                ip_int += ip_profile['dhcp_count']
+                ip_int += ip_profile['dhcp_count'] - 1
                 ip_str = str(netaddr.IPAddress(ip_int))
                 subnet['allocation_pools'][0]['end'] = ip_str
                 ip_str = str(netaddr.IPAddress(ip_int))
                 subnet['allocation_pools'][0]['end'] = ip_str
+            #self.logger.debug(">>>>>>>>>>>>>>>>>> Subnet: %s", str(subnet))
             self.neutron.create_subnet({"subnet": subnet} )
             return new_net["network"]["id"]
         except (neExceptions.ConnectionFailed, ksExceptions.ClientException, neExceptions.NeutronException, ConnectionError) as e:
             self.neutron.create_subnet({"subnet": subnet} )
             return new_net["network"]["id"]
         except (neExceptions.ConnectionFailed, ksExceptions.ClientException, neExceptions.NeutronException, ConnectionError) as e:
+            if new_net:
+                self.neutron.delete_network(new_net['network']['id'])
             self._format_exception(e)
 
     def get_network_list(self, filter_dict={}):
             self._format_exception(e)
 
     def get_network_list(self, filter_dict={}):
@@ -291,6 +338,8 @@ class vimconnector(vimconn.vimconnector):
         self.logger.debug("Getting network from VIM filter: '%s'", str(filter_dict))
         try:
             self._reload_connection()
         self.logger.debug("Getting network from VIM filter: '%s'", str(filter_dict))
         try:
             self._reload_connection()
+            if osc_api_version == 'v3.3' and "tenant_id" in filter_dict:
+                filter_dict['project_id'] = filter_dict.pop('tenant_id')
             net_dict=self.neutron.list_networks(**filter_dict)
             net_list=net_dict["networks"]
             self.__net_os2mano(net_list)
             net_dict=self.neutron.list_networks(**filter_dict)
             net_list=net_dict["networks"]
             self.__net_os2mano(net_list)
@@ -593,7 +642,7 @@ class vimconnector(vimconn.vimconnector):
             #Then we filter by the rest of filter fields: checksum
             filtered_list = []
             for image in image_list:
             #Then we filter by the rest of filter fields: checksum
             filtered_list = []
             for image in image_list:
-                image_dict=glance.images.get(image.id)
+                image_dict=self.glance.images.get(image.id)
                 if image_dict['checksum']==filter_dict.get('checksum'):
                     filtered_list.append(image)
             return filtered_list
                 if image_dict['checksum']==filter_dict.get('checksum'):
                     filtered_list.append(image)
             return filtered_list