X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=vimconn_openstack.py;h=81c6591531ed7578b447c9be3d76b59fd4be0d34;hb=refs%2Fchanges%2F52%2F752%2F1;hp=857b181af5230a998111e2a4b190ad76afe5d28a;hpb=8e995ced65fe608f254318c496c769a4f3852466;p=osm%2FRO.git diff --git a/vimconn_openstack.py b/vimconn_openstack.py index 857b181a..81c65915 100644 --- a/vimconn_openstack.py +++ b/vimconn_openstack.py @@ -24,8 +24,8 @@ ''' 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 @@ -33,14 +33,17 @@ import yaml 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 -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 @@ -56,11 +59,14 @@ netStatus2manoFormat={'ACTIVE':'ACTIVE','PAUSED':'PAUSED','INACTIVE':'INACTIVE', } 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 ''' + 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={} @@ -81,8 +87,13 @@ class vimconnector(vimconn.vimconnector): 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') + if log_level: + self.logger.setLevel( getattr(logging, log_level) ) 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 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: - 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 - 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: - 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 @@ -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") - 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.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 - + 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): Returns the tenant list of dictionaries: [{'name':', '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() - 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) @@ -209,8 +245,11 @@ class vimconnector(vimconn.vimconnector): 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) @@ -219,15 +258,20 @@ class vimconnector(vimconn.vimconnector): 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) - + 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: + new_net = None 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 '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']) @@ -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'])) - 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 + #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: + if new_net: + self.neutron.delete_network(new_net['network']['id']) 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() + 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) @@ -560,8 +609,7 @@ class vimconnector(vimconn.vimconnector): self._format_exception(e) def get_image_id_from_path(self, path): - '''Get the image id from image path in the VIM database. Returns the image_id - ''' + '''Get the image id from image path in the VIM database. Returns the image_id''' try: self._reload_connection() images = self.nova.images.list() @@ -572,6 +620,35 @@ class vimconnector(vimconn.vimconnector): except (ksExceptions.ClientException, nvExceptions.ClientException, gl1Exceptions.CommunicationError, ConnectionError) as e: self._format_exception(e) + def get_image_list(self, filter_dict={}): + '''Obtain tenant images from VIM + Filter_dict can be: + id: image id + name: image name + checksum: image checksum + Returns the image list of dictionaries: + [{}, ...] + List can be empty + ''' + self.logger.debug("Getting image list from VIM filter: '%s'", str(filter_dict)) + try: + self._reload_connection() + filter_dict_os=filter_dict.copy() + #First we filter by the available filter fields: name, id. The others are removed. + filter_dict_os.pop('checksum',None) + image_list=self.nova.images.findall(**filter_dict_os) + if len(image_list)==0: + return [] + #Then we filter by the rest of filter fields: checksum + filtered_list = [] + for image in image_list: + image_dict=self.glance.images.get(image.id) + if image_dict['checksum']==filter_dict.get('checksum'): + filtered_list.append(image) + return filtered_list + except (ksExceptions.ClientException, nvExceptions.ClientException, gl1Exceptions.CommunicationError, ConnectionError) as e: + self._format_exception(e) + def new_vminstance(self,name,description,start,image_id,flavor_id,net_list,cloud_config=None): '''Adds a VM instance to VIM Params: