X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=vimconn_openstack.py;h=9b9a2c0fb387a09e7de10c1e7def059f5368d0f4;hb=867ffe95de6cadcc001e0a57ed26750ba8c01a32;hp=eaeae92f0ab209d1eb65ddfbf24d74179a56a73a;hpb=4540ea5619ae62e29ecec6b07bf0e81e35fd56f0;p=osm%2FRO.git diff --git a/vimconn_openstack.py b/vimconn_openstack.py index eaeae92f..9b9a2c0f 100644 --- a/vimconn_openstack.py +++ b/vimconn_openstack.py @@ -34,8 +34,10 @@ import logging import netaddr import time import yaml +import random -from novaclient import client as nClient_v2, exceptions as nvExceptions, api_versions as APIVersion +from novaclient import client as nClient_v2, exceptions as nvExceptions +from novaclient import api_versions import keystoneclient.v2_0.client as ksClient_v2 from novaclient.v2.client import Client as nClient import keystoneclient.v3.client as ksClient @@ -66,8 +68,9 @@ volume_timeout = 60 server_timeout = 60 class vimconnector(vimconn.vimconnector): - 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 + def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, + log_level=None, config={}, persistent_info={}): + '''using common constructor parameters. In this case 'url' is the keystone authorization url, 'url_admin' is not use ''' @@ -75,7 +78,8 @@ class vimconnector(vimconn.vimconnector): 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.persistent_info = persistent_info self.k_creds={} self.n_creds={} if self.config.get("insecure"): @@ -186,14 +190,14 @@ class vimconnector(vimconn.vimconnector): if len(self.n_creds) <4: raise ksExceptions.ClientException("Not enough parameters to connect to openstack") if self.osc_api_version == 'v3.3': - self.nova = nClient(APIVersion(version_str='2'), **self.n_creds) + self.nova = nClient(api_version=api_versions.APIVersion(version_str='2.0'), **self.n_creds) #TODO To be updated for v3 #self.cinder = cClient.Client(**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) + self.neutron = neClient.Client(api_version=api_versions.APIVersion(version_str='2.0'), endpoint_url=self.ne_endpoint, token=self.keystone.auth_token, **self.k_creds) else: - self.nova = nClient_v2.Client('2', **self.n_creds) + self.nova = nClient_v2.Client(version='2', **self.n_creds) self.cinder = cClient_v2.Client(**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') @@ -305,8 +309,9 @@ class vimconnector(vimconn.vimconnector): if not ip_profile: ip_profile = {} if 'subnet_address' not in ip_profile: - #Fake subnet is required - ip_profile['subnet_address'] = "192.168.111.0/24" + #Fake subnet is required + subnet_rand = random.randint(0, 255) + ip_profile['subnet_address'] = "192.168.{}.0/24".format(subnet_rand) if 'ip_version' not in ip_profile: ip_profile['ip_version'] = "IPv4" subnet={"name":net_name+"-subnet", @@ -384,6 +389,8 @@ class vimconnector(vimconn.vimconnector): subnet = {"id": subnet_id, "fault": str(e)} subnets.append(subnet) net["subnets"] = subnets + net["encapsulation"] = net.get('provider:network_type') + net["segmentation_id"] = net.get('provider:segmentation_id') return net def delete_network(self, net_id): @@ -462,6 +469,38 @@ class vimconnector(vimconn.vimconnector): except (nvExceptions.NotFound, nvExceptions.ClientException, ksExceptions.ClientException, ConnectionError) as e: self._format_exception(e) + def get_flavor_id_from_data(self, flavor_dict): + """Obtain flavor id that match the flavor description + Returns the flavor_id or raises a vimconnNotFoundException + """ + try: + self._reload_connection() + numa=None + numas = flavor_dict.get("extended",{}).get("numas") + if numas: + #TODO + raise vimconn.vimconnNotFoundException("Flavor with EPA still not implemted") + # if len(numas) > 1: + # raise vimconn.vimconnNotFoundException("Cannot find any flavor with more than one numa") + # numa=numas[0] + # numas = extended.get("numas") + for flavor in self.nova.flavors.list(): + epa = flavor.get_keys() + if epa: + continue + #TODO + if flavor.ram != flavor_dict["ram"]: + continue + if flavor.vcpus != flavor_dict["vcpus"]: + continue + if flavor.disk != flavor_dict["disk"]: + continue + return flavor.id + raise vimconn.vimconnNotFoundException("Cannot find any flavor matching '{}'".format(str(flavor_dict))) + except (nvExceptions.NotFound, nvExceptions.ClientException, ksExceptions.ClientException, ConnectionError) as e: + self._format_exception(e) + + def new_flavor(self, flavor_data, change_name_if_used=True): '''Adds a tenant flavor to openstack VIM if change_name_if_used is True, it will change name in case of conflict, because it is not supported name repetition @@ -684,7 +723,7 @@ class vimconnector(vimconn.vimconnector): #TODO ip, security groups Returns the instance identifier ''' - self.logger.debug("Creating VM image '%s' flavor '%s' nics='%s'",image_id, flavor_id,str(net_list)) + self.logger.debug("new_vminstance input: image='%s' flavor='%s' nics='%s'",image_id, flavor_id,str(net_list)) try: metadata={} net_list_vim=[] @@ -761,7 +800,7 @@ class vimconnector(vimconn.vimconnector): userdata_dict["ssh-authorized-keys"] = cloud_config["key-pairs"] userdata_dict["users"] = [{"default": None, "ssh-authorized-keys": cloud_config["key-pairs"] }] if cloud_config.get("users"): - if "users" not in cloud_config: + if "users" not in userdata_dict: userdata_dict["users"] = [ "default" ] for user in cloud_config["users"]: user_info = { @@ -1055,6 +1094,9 @@ class vimconnector(vimconn.vimconnector): vim_net_id: #network id where this interface is connected vim_interface_id: #interface/port VIM id ip_address: #null, or text with IPv4, IPv6 address + compute_node: #identification of compute node where PF,VF interface is allocated + pci: #PCI address of the NIC that hosts the PF,VF + vlan: #physical VLAN used for VF ''' vm_dict={} self.logger.debug("refresh_vms status: Getting tenant VM instance information from VIM") @@ -1087,6 +1129,19 @@ class vimconnector(vimconn.vimconnector): interface["mac_address"] = port.get("mac_address") interface["vim_net_id"] = port["network_id"] interface["vim_interface_id"] = port["id"] + interface["compute_node"] = vm_vim['OS-EXT-SRV-ATTR:host'] + interface["pci"] = None + if port['binding:profile'].get('pci_slot'): + # TODO: At the moment sr-iov pci addresses are converted to PF pci addresses by setting the slot to 0x00 + # TODO: This is just a workaround valid for niantinc. Find a better way to do so + # CHANGE DDDD:BB:SS.F to DDDD:BB:00.(F%2) assuming there are 2 ports per nic + pci = port['binding:profile']['pci_slot'] + # interface["pci"] = pci[:-4] + "00." + str(int(pci[-1]) % 2) + interface["pci"] = pci + interface["vlan"] = None + network = self.neutron.show_network(port["network_id"]) + if network['network'].get('provider:network_type') == 'vlan': + interface["vlan"] = network['network'].get('provider:segmentation_id') ips=[] #look for floating ip address floating_ip_dict = self.neutron.list_floatingips(port_id=port["id"])