X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_ro%2Fvimconn_azure.py;fp=osm_ro%2Fvimconn_azure.py;h=0000000000000000000000000000000000000000;hb=7d782eff123e5b44d41437377ccca66ad1e8b21b;hp=24a9878d5c58ea93c0c585f47a7c5498125ce504;hpb=5db670b68349fd1f00a5efc8c0ccd0ef9d073dca;p=osm%2FRO.git diff --git a/osm_ro/vimconn_azure.py b/osm_ro/vimconn_azure.py deleted file mode 100755 index 24a9878d..00000000 --- a/osm_ro/vimconn_azure.py +++ /dev/null @@ -1,495 +0,0 @@ -# -*- coding: utf-8 -*- - -__author__='Sergio Gonzalez' -__date__ ='$18-apr-2019 23:59:59$' - -import vimconn -import logging - -from os import getenv -from uuid import uuid4 - -from azure.common.credentials import ServicePrincipalCredentials -from azure.mgmt.resource import ResourceManagementClient -from azure.mgmt.network import NetworkManagementClient -from azure.mgmt.compute import ComputeManagementClient - - -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={}, persistent_info={}): - - vimconn.vimconnector.__init__(self, uuid, name, tenant_id, tenant_name, url, url_admin, user, passwd, log_level, - config, persistent_info) - - # LOGGER - self.logger = logging.getLogger('openmano.vim.azure') - if log_level: - logging.basicConfig() - self.logger.setLevel(getattr(logging, log_level)) - - # CREDENTIALS - self.credentials = ServicePrincipalCredentials( - client_id=user, - secret=passwd, - tenant=(tenant_id or tenant_name) - ) - - # SUBSCRIPTION - if 'subscription_id' in config: - self.subscription_id = config.get('subscription_id') - self.logger.debug('Setting subscription '+str(self.subscription_id)) - else: - raise vimconn.vimconnException('Subscription not specified') - # REGION - if 'region_name' in config: - self.region = config.get('region_name') - else: - raise vimconn.vimconnException('Azure region_name is not specified at config') - # RESOURCE_GROUP - if 'resource_group' in config: - self.resource_group = config.get('resource_group') - else: - raise vimconn.vimconnException('Azure resource_group is not specified at config') - # VNET_NAME - if 'vnet_name' in config: - self.vnet_name = config["vnet_name"] - - # public ssh key - self.pub_key = config.get('pub_key') - - def _reload_connection(self): - """ - 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) - - def _get_resource_name_from_resource_id(self, resource_id): - return str(resource_id.split('/')[-1]) - - def _get_location_from_resource_group(self, resource_group_name): - return self.conn.resource_groups.get(resource_group_name).location - - def _get_resource_group_name_from_resource_id(self, resource_id): - return str(resource_id.split('/')[4]) - - def _check_subnets_for_vm(self, net_list): - # All subnets must belong to the same resource group and vnet - if len(set(self._get_resource_group_name_from_resource_id(net['id']) + - self._get_resource_name_from_resource_id(net['id']) for net in net_list)) != 1: - 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 - :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 - :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}) - - def _check_or_create_vnet(self): - try: - vnet_params = { - 'location': self.region, - 'address_space': { - 'address_prefixes': "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 - :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 - 'dns-address': (Optional) ip_schema, - 'dhcp': (Optional) dict containing - 'enabled': {'type': 'boolean'}, - 'start-address': ip_schema, first IP to grant - 'count': number of IPs to grant. - :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 - :param net_name: - :param ip_profile: - :return: - """ - self.logger.debug('Adding a subnet to VNET '+self.vnet_name) - self._reload_connection() - - if ip_profile is None: - # TODO get a non used vnet ip range /24 and allocate automatically - 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()), - 'address_prefix': ip_profile['subnet_address'] - } - ] - } - self.conn_vnet.virtual_networks.create_or_update(self.resource_group, self.vnet_name, vnet_params) - # TODO return a tuple (subnet-ID, None) - except Exception as e: - self.format_vimconn_exception(e) - - def _create_nic(self, subnet_id, nic_name, static_ip=None): - self._reload_connection() - - resource_group_name=self._get_resource_group_name_from_resource_id(subnet_id) - location = self._get_location_from_resource_group(resource_group_name) - - if static_ip: - async_nic_creation = self.conn_vnet.network_interfaces.create_or_update( - resource_group_name, - nic_name, - { - 'location': location, - 'ip_configurations': [{ - 'name': nic_name + 'ipconfiguration', - 'privateIPAddress': static_ip, - 'privateIPAllocationMethod': 'Static', - 'subnet': { - 'id': subnet_id - } - }] - } - ) - else: - async_nic_creation = self.conn_vnet.network_interfaces.create_or_update( - resource_group_name, - nic_name, - { - 'location': location, - 'ip_configurations': [{ - 'name': nic_name + 'ipconfiguration', - 'subnet': { - 'id': subnet_id - } - }] - } - ) - - 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 - Filter_dict can be: - name: network name - id: network uuid - shared: boolean - tenant_id: tenant - admin_state_up: boolean - status: 'ACTIVE' - Returns the network list of dictionaries - """ - self.logger.debug('Getting all subnets from VIM') - try: - self._reload_connection() - vnet = self.conn_vnet.virtual_networks.get(self.config["resource_group"], self.vnet_name) - subnet_list = [] - - for subnet in vnet.subnets: - # TODO implement filter_dict - if filter_dict: - if filter_dict.get("id") and str(subnet.id) != filter_dict["id"]: - continue - if filter_dict.get("name") and \ - self._get_resource_name_from_resource_id(subnet.id) != filter_dict["name"]: - continue - - subnet_list.append({ - 'id': str(subnet.id), - 'name': self._get_resource_name_from_resource_id(subnet.id), - 'status': str(vnet.provisioning_state), # TODO Does subnet contains status??? - 'cidr_block': str(subnet.address_prefix) - } - ) - return subnet_list - except Exception as e: - self.format_vimconn_exception(e) - - def new_vminstance(self, vm_name, description, start, image_id, flavor_id, net_list, cloud_config=None, - disk_list=None, availability_zone_index=None, availability_zone_list=None): - - return self._new_vminstance(vm_name, image_id, flavor_id, net_list) - - def _new_vminstance(self, vm_name, image_id, flavor_id, net_list, cloud_config=None, disk_list=None, - availability_zone_index=None, availability_zone_list=None): - #Create NICs - self._check_subnets_for_vm(net_list) - vm_nics = [] - for idx, net in enumerate(net_list): - subnet_id=net['subnet_id'] - nic_name = vm_name + '-nic-'+str(idx) - vm_nic = self._create_nic(subnet_id, nic_name) - vm_nics.append({ 'id': str(vm_nic.id)}) - - try: - vm_parameters = { - 'location': self.region, - 'os_profile': { - 'computer_name': vm_name, # TODO if vm_name cannot be repeated add uuid4() suffix - 'admin_username': 'sergio', # TODO is it mandatory??? - 'linuxConfiguration': { - 'disablePasswordAuthentication': 'true', - 'ssh': { - 'publicKeys': [ - { - 'path': '/home/sergio/.ssh/authorized_keys', - 'keyData': self.pub_key - } - ] - } - } - - }, - 'hardware_profile': { - 'vm_size':flavor_id - }, - 'storage_profile': { - 'image_reference': image_id - }, - 'network_profile': { - 'network_interfaces': [ - vm_nics[0] - ] - } - } - creation_result = self.conn_compute.virtual_machines.create_or_update( - self.resource_group, - vm_name, - vm_parameters - ) - - run_command_parameters = { - 'command_id': 'RunShellScript', # For linux, don't change it - 'script': [ - 'date > /home/sergio/test.txt' - ] - } - poller = self.conn_compute.virtual_machines.run_command( - self.resource_group, - vm_name, - run_command_parameters - ) - # TODO return a tuple (vm-ID, None) - except Exception as e: - self.format_vimconn_exception(e) - - def get_flavor_id_from_data(self, flavor_dict): - self.logger.debug("Getting flavor id from data") - self._reload_connection() - vm_sizes_list = [vm_size.serialize() for vm_size in self.conn_compute.virtual_machine_sizes.list(self.region)] - - cpus = flavor_dict['vcpus'] - memMB = flavor_dict['ram'] - - filteredSizes = [size for size in vm_sizes_list if size['numberOfCores'] > cpus and size['memoryInMB'] > memMB] - listedFilteredSizes = sorted(filteredSizes, key=lambda k: k['numberOfCores']) - - return listedFilteredSizes[0]['name'] - - def check_vim_connectivity(self): - try: - self._reload_connection() - return True - except Exception as e: - raise vimconn.vimconnException("Connectivity issue with Azure API: {}".format(e)) - - def get_network(self, net_id): - resGroup = self._get_resource_group_name_from_resource_id(net_id) - resName = self._get_resource_name_from_resource_id(net_id) - - self._reload_connection() - vnet = self.conn_vnet.virtual_networks.get(resGroup, resName) - - return vnet - - def delete_network(self, net_id): - resGroup = self._get_resource_group_name_from_resource_id(net_id) - resName = self._get_resource_name_from_resource_id(net_id) - - self._reload_connection() - self.conn_vnet.virtual_networks.delete(resGroup, resName) - - def delete_vminstance(self, vm_id): - resGroup = self._get_resource_group_name_from_resource_id(net_id) - resName = self._get_resource_name_from_resource_id(net_id) - - self._reload_connection() - self.conn_compute.virtual_machines.delete(resGroup, resName) - - def get_vminstance(self, vm_id): - resGroup = self._get_resource_group_name_from_resource_id(net_id) - resName = self._get_resource_name_from_resource_id(net_id) - - self._reload_connection() - vm=self.conn_compute.virtual_machines.get(resGroup, resName) - - return vm - - def get_flavor(self, flavor_id): - self._reload_connection() - for vm_size in self.conn_compute.virtual_machine_sizes.list(self.region): - if vm_size.name == flavor_id : - return vm_size - - -# TODO refresh_nets_status ver estado activo -# TODO refresh_vms_status ver estado activo -# TODO get_vminstance_console for getting console - -if __name__ == "__main__": - - # Making some basic test - vim_id='azure' - vim_name='azure' - needed_test_params = { - "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 = {} - - for param, env_var in needed_test_params.items(): - value = getenv(env_var) - if not value: - raise Exception("Provide a valid value for env '{}'".format(env_var)) - test_params[param] = value - - config = { - 'region_name': getenv("AZURE_REGION_NAME", 'westeurope'), - 'resource_group': getenv("AZURE_RESOURCE_GROUP"), - 'subscription_id': getenv("AZURE_SUBSCRIPTION_ID"), - 'pub_key': getenv("AZURE_PUB_KEY", None), - 'vnet_name': getenv("AZURE_VNET_NAME", 'myNetwork'), - } - - virtualMachine = { - 'name': 'sergio', - 'description': 'new VM', - 'status': 'running', - 'image': { - 'publisher': 'Canonical', - 'offer': 'UbuntuServer', - 'sku': '16.04.0-LTS', - 'version': 'latest' - }, - 'hardware_profile': { - 'vm_size': 'Standard_DS1_v2' - }, - 'networks': [ - 'sergio' - ] - } - - vnet_config = { - 'subnet_address': '10.1.2.0/24', - #'subnet_name': 'subnet-oam' - } - ########################### - - 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