X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=osm_ro%2Fvimconn_azure.py;h=c2e7206fe62ae99f46efd8fe1941e376480245bc;hb=refs%2Fchanges%2F68%2F7568%2F1;hp=3bb7c249aa2e31ae780d83797abb6e0e7ad6cf8a;hpb=30d0d6dfa518c5e439f4e004b97201b0eb51680a;p=osm%2FRO.git diff --git a/osm_ro/vimconn_azure.py b/osm_ro/vimconn_azure.py index 3bb7c249..c2e7206f 100755 --- a/osm_ro/vimconn_azure.py +++ b/osm_ro/vimconn_azure.py @@ -14,14 +14,24 @@ from azure.mgmt.resource import ResourceManagementClient from azure.mgmt.network import NetworkManagementClient from azure.mgmt.compute import ComputeManagementClient +from msrestazure.azure_exceptions import CloudError + class vimconnector(vimconn.vimconnector): + provision_state2osm = { + "Deleting": "INACTIVE", + "Failed": "ERROR", + "Succeeded": "ACTIVE", + "Updating": "BUILD", + } + def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None, config={}, persistent_info={}): vimconn.vimconnector.__init__(self, uuid, name, tenant_id, tenant_name, url, url_admin, user, passwd, log_level, config, persistent_info) + self.vnet_address_space = None # LOGGER self.logger = logging.getLogger('openmano.vim.azure') if log_level: @@ -59,13 +69,17 @@ class vimconnector(vimconn.vimconnector): self.pub_key = config.get('pub_key') def _reload_connection(self): - '''Sets connections to work with Azure service APIs - ''' + """ + Sets connections to work with Azure service APIs + :return: + """ self.logger.debug('Reloading API Connection') try: self.conn = ResourceManagementClient(self.credentials, self.subscription_id) self.conn_compute = ComputeManagementClient(self.credentials, self.subscription_id) self.conn_vnet = NetworkManagementClient(self.credentials, self.subscription_id) + self._check_or_create_resource_group() + self._check_or_create_vnet() except Exception as e: self.format_vimconn_exception(e) @@ -85,24 +99,52 @@ class vimconnector(vimconn.vimconnector): raise self.format_vimconn_exception('Azure VMs can only attach to subnets in same VNET') def format_vimconn_exception(self, e): - '''Params: an Exception object - Returns: Raises the exception 'e' passed in mehtod parameters - ''' + """ + Params: an Exception object + :param e: + :return: Raises the proper vimconnException + """ self.conn = None self.conn_vnet = None raise vimconn.vimconnConnectionException(type(e).__name__ + ': ' + str(e)) def _check_or_create_resource_group(self): - '''Creates a resource group in indicated region - ''' + """ + Creates a resource group in indicated region + :return: None + """ self.logger.debug('Creating RG {} in location {}'.format(self.resource_group, self.region)) - self.conn.resource_groups.create_or_update(self.resource_group, {'location':self.region}) + self.conn.resource_groups.create_or_update(self.resource_group, {'location': self.region}) + + def _check_or_create_vnet(self): + try: + vnet = self.conn_vnet.virtual_networks.get(self.resource_group, self.vnet_name) + self.vnet_address_space = vnet.address_space.address_prefixes[0] + return + except CloudError as e: + if e.error.error == "ResourceNotFound": + pass + else: + raise + # if not exist, creates it + try: + vnet_params = { + 'location': self.region, + 'address_space': { + 'address_prefixes': ["10.0.0.0/8"] + }, + } + self.vnet_address_space = "10.0.0.0/8" + self.conn_vnet.virtual_networks.create_or_update(self.resource_group, self.vnet_name, vnet_params) + except Exception as e: + self.format_vimconn_exception(e) def new_network(self, net_name, net_type, ip_profile=None, shared=False, vlan=None): - '''Adds a tenant network to VIM - Params: - 'net_name': name of the network - 'ip_profile': is a dict containing the IP parameters of the network (Currently only IPv4 is implemented) + """ + Adds a tenant network to VIM + :param net_name: name of the network + :param net_type: + :param ip_profile: is a dict containing the IP parameters of the network (Currently only IPv4 is implemented) 'ip-version': can be one of ['IPv4','IPv6'] 'subnet-address': ip_prefix_schema, that is X.X.X.X/Y 'gateway-address': (Optional) ip_schema, that is X.X.X.X @@ -111,32 +153,35 @@ class vimconnector(vimconn.vimconnector): 'enabled': {'type': 'boolean'}, 'start-address': ip_schema, first IP to grant 'count': number of IPs to grant. - Returns a tuple with the network identifier and created_items, or raises an exception on error + :param shared: + :param vlan: + :return: a tuple with the network identifier and created_items, or raises an exception on error created_items can be None or a dictionary where this method can include key-values that will be passed to the method delete_network. Can be used to store created segments, created l2gw connections, etc. Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same as not present. - ''' + """ + return self._new_subnet(net_name, ip_profile) def _new_subnet(self, net_name, ip_profile): - '''Adds a tenant network to VIM - It creates a new VNET with a single subnet - ''' + """ + Adds a tenant network to VIM. It creates a new VNET with a single subnet + :param net_name: + :param ip_profile: + :return: + """ self.logger.debug('Adding a subnet to VNET '+self.vnet_name) self._reload_connection() - self._check_or_create_resource_group() if ip_profile is None: - # TODO get a non used vnet ip range /24 and allocate automatically + # TODO get a non used vnet ip range /24 and allocate automatically inside the range self.vnet_address_space + # use netaddr library raise vimconn.vimconnException('Azure cannot create VNET with no CIDR') try: vnet_params= { 'location': self.region, - 'address_space': { - 'address_prefixes': [ip_profile['subnet_address']] - }, 'subnets': [ { 'name': "{}-{}".format(net_name[:24], uuid4()), @@ -188,8 +233,56 @@ class vimconnector(vimconn.vimconnector): return async_nic_creation.result() + def get_image_list(self, filter_dict={}): + """ + The urn contains for marketplace 'publisher:offer:sku:version' + + :param filter_dict: + :return: + """ + image_list = [] + + self._reload_connection() + if filter_dict.get("name"): + params = filter_dict["name"].split(":") + if len(params) >= 3: + publisher = params[0] + offer = params[1] + sku = params[2] + version = None + if len(params) == 4: + version = params[3] + images = self.conn_compute.virtual_machine_images.list(self.region, publisher, offer, sku) + for image in images: + if version: + image_version = str(image.id).split("/")[-1] + if image_version != version: + continue + image_list.append({ + 'id': str(image.id), + 'name': self._get_resource_name_from_resource_id(image.id) + }) + return image_list + + images = self.conn_compute.virtual_machine_images.list() + + for image in images: + # TODO implement filter_dict + if filter_dict: + if filter_dict.get("id") and str(image.id) != filter_dict["id"]: + continue + if filter_dict.get("name") and \ + self._get_resource_name_from_resource_id(image.id) != filter_dict["name"]: + continue + # TODO add checksum + image_list.append({ + 'id': str(image.id), + 'name': self._get_resource_name_from_resource_id(image.id), + }) + return image_list + def get_network_list(self, filter_dict={}): - '''Obtain tenant networks of VIM + """Obtain tenant networks of VIM Filter_dict can be: name: network name id: network uuid @@ -198,7 +291,7 @@ class vimconnector(vimconn.vimconnector): admin_state_up: boolean status: 'ACTIVE' Returns the network list of dictionaries - ''' + """ self.logger.debug('Getting all subnets from VIM') try: self._reload_connection() @@ -351,10 +444,66 @@ class vimconnector(vimconn.vimconnector): if vm_size.name == flavor_id : return vm_size + def refresh_nets_status(self, net_list): + out_nets = {} + self._reload_connection() + for net_id in net_list: + try: + resGroup = self._get_resource_group_name_from_resource_id(net_id) + resName = self._get_resource_name_from_resource_id(net_id) + + vnet = self.conn_vnet.virtual_networks.get(resGroup, resName) + out_nets[net_id] ={ + "status": self.provision_state2osm[vnet.provisioning_state], + "vim_info": str(vnet) + } + except CloudError as e: + if e.error.error == "ResourceNotFound": + out_nets[net_id] = { + "status": "DELETED", + } + else: + raise + except Exception as e: + # TODO distinguish when it is deleted + out_nets[net_id] = { + "status": "VIM_ERROR", + "vim_info": str(vnet), + "error_msg": str(e) + } + + return out_nets + + def refresh_vms_status(self, vm_list): + out_vms = {} + self._reload_connection() + for vm_id in vm_list: + try: + resGroup = self._get_resource_group_name_from_resource_id(vm_id) + resName = self._get_resource_name_from_resource_id(vm_id) + + vm = self.conn_compute.virtual_machines.get(resGroup, resName) + out_vms[vm_id] ={ + "status": self.provision_state2osm[vm.provisioning_state], + "vim_info": str(vm) + } + except CloudError as e: + if e.error.error == "ResourceNotFound": + out_vms[vm_id] = { + "status": "DELETED", + } + else: + raise + except Exception as e: + # TODO distinguish when it is deleted + out_vms[vm_id] = { + "status": "VIM_ERROR", + "vim_info": str(vm), + "error_msg": str(e) + } + + return out_vms -# TODO refresh_nets_status ver estado activo -# TODO PRIORITARY get_image_list -# TODO refresh_vms_status ver estado activo # TODO get_vminstance_console for getting console if __name__ == "__main__": @@ -363,12 +512,11 @@ if __name__ == "__main__": vim_id='azure' vim_name='azure' needed_test_params = { - "client_id": "AZURE_CLIENT_ID", # TODO delete private information - "secret": "AZURE_SECRET", # TODO delete private information - "tenant": "AZURE_TENANT", # TODO delete private information - "resource_group": "AZURE_RESOURCE_GROUP", # TODO delete private information # 'testOSMlive2', - # TODO maybe it should be created a resouce_group per VNFD - "subscription_id": "AZURE_SUBSCRIPTION_ID", # TODO delete private information 'ca3d18ab-d373-4afb-a5d6-7c44f098d16a' + "client_id": "AZURE_CLIENT_ID", + "secret": "AZURE_SECRET", + "tenant": "AZURE_TENANT", + "resource_group": "AZURE_RESOURCE_GROUP", + "subscription_id": "AZURE_SUBSCRIPTION_ID", "vnet_name": "AZURE_VNET_NAME", } test_params = {} @@ -414,9 +562,13 @@ if __name__ == "__main__": azure = vimconnector(vim_id, vim_name, tenant_id=test_params["tenant"], tenant_name=None, url=None, url_admin=None, user=test_params["client_id"], passwd=test_params["secret"], log_level=None, config=config) - #azure.get_flavor_id_from_data("here") - #subnets=azure.get_network_list() - #azure.new_vminstance(virtualMachine['name'], virtualMachine['description'], virtualMachine['status'], - # virtualMachine['image'], virtualMachine['hardware_profile']['vm_size'], subnets) - # - azure.get_flavor("Standard_A11") \ No newline at end of file + # azure.get_flavor_id_from_data("here") + # subnets=azure.get_network_list() + # azure.new_vminstance(virtualMachine['name'], virtualMachine['description'], virtualMachine['status'], + # virtualMachine['image'], virtualMachine['hardware_profile']['vm_size'], subnets) + + net_id = "/subscriptions/82f80cc1-876b-4591-9911-1fb5788384fd/resourceGroups/osmRG/providers/Microsoft."\ + "Network/virtualNetworks/test" + net_id_not_found = "/subscriptions/82f80cc1-876b-4591-9911-1fb5788384fd/resourceGroups/osmRG/providers/"\ + "Microsoft.Network/virtualNetworks/testALF" + azure.refresh_nets_status([net_id, net_id_not_found])