X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FRO.git;a=blobdiff_plain;f=RO-VIM-gcp%2Fosm_rovim_gcp%2Fvimconn_gcp.py;h=0109bf12ba9232cf189ad2c41619d0cb975fdd6f;hp=67d8c410773e41cf0044c613bdc22fe7a019f320;hb=HEAD;hpb=29a4c1a24050561a70f4f47b276a268d48c79067 diff --git a/RO-VIM-gcp/osm_rovim_gcp/vimconn_gcp.py b/RO-VIM-gcp/osm_rovim_gcp/vimconn_gcp.py index 67d8c410..0109bf12 100644 --- a/RO-VIM-gcp/osm_rovim_gcp/vimconn_gcp.py +++ b/RO-VIM-gcp/osm_rovim_gcp/vimconn_gcp.py @@ -19,9 +19,6 @@ import random from random import choice as random_choice import time -from cryptography.hazmat.backends import default_backend as crypto_default_backend -from cryptography.hazmat.primitives import serialization as crypto_serialization -from cryptography.hazmat.primitives.asymmetric import rsa from google.oauth2 import service_account import googleapiclient.discovery from osm_ro_plugin import vimconn @@ -40,7 +37,6 @@ if getenv("OSMRO_PDB_DEBUG"): class vimconnector(vimconn.VimConnector): - # Translate Google Cloud provisioning state to OSM provision state # The first three ones are the transitional status once a user initiated action has been requested # Once the operation is complete, it will transition into the states Succeeded or Failed @@ -187,7 +183,9 @@ class vimconnector(vimconn.VimConnector): try: # Set to client created - self.conn_compute = googleapiclient.discovery.build("compute", "v1") + self.conn_compute = googleapiclient.discovery.build( + "compute", "v1", credentials=self.credentials + ) except Exception as e: self._format_vimconn_exception(e) @@ -306,7 +304,6 @@ class vimconnector(vimconn.VimConnector): self.logger.debug("create network name %s, ip_profile %s", net_name, ip_profile) try: - self.logger.debug("creating network_name: {}".format(net_name)) network = "projects/{}/global/networks/default".format(self.project) @@ -375,7 +372,6 @@ class vimconnector(vimconn.VimConnector): ) try: - self.logger.debug("creating subnet_name: {}".format(subnet_name)) subnetwork_body = { @@ -424,7 +420,6 @@ class vimconnector(vimconn.VimConnector): ) try: - if self.reload_client: self._reload_connection() @@ -504,7 +499,6 @@ class vimconnector(vimconn.VimConnector): self.logger.debug("Deleting network: {}".format(str(net_id))) try: - net_name = self._get_resource_name_from_resource_id(net_id) # Check associated VMs @@ -814,9 +808,6 @@ class vimconnector(vimconn.VimConnector): except Exception as e: self._format_vimconn_exception(e) - def delete_inuse_nic(self, nic_name): - raise vimconn.VimConnNotImplemented("Not necessary") - def delete_image(self, image_id): raise vimconn.VimConnNotImplemented("Not implemented") @@ -913,11 +904,14 @@ class vimconnector(vimconn.VimConnector): if not net.get("name"): continue else: - net_iface[ - "subnetwork" - ] = "regions/%s/subnetworks/" % self.region + net.get("name") + net_iface["subnetwork"] = ( + "regions/%s/subnetworks/" % self.region + net.get("name") + ) else: net_iface["subnetwork"] = net.get("net_id") + if net.get("ip_address"): + net_iface["networkIP"] = net.get("ip_address") + # In order to get an external IP address, the key "accessConfigs" must be used # in the interace. It has to be of type "ONE_TO_ONE_NAT" and name "External NAT" if net.get("floating_ip", False) or ( @@ -1019,85 +1013,10 @@ class vimconnector(vimconn.VimConnector): # either password of ssh-keys are required # we will always use ssh-keys, in case it is not available we will generate it - """ - if cloud_config and cloud_config.get("key-pairs"): - key_data = "" - key_pairs = {} - if cloud_config.get("key-pairs"): - if isinstance(cloud_config["key-pairs"], list): - # Transform the format " " into ":" - key_data = "" - for key in cloud_config.get("key-pairs"): - key_data = key_data + key + "\n" - key_pairs = { - "key": "ssh-keys", - "value": key_data - } - else: - # If there is no ssh key in cloud config, a new key is generated: - _, key_data = self._generate_keys() - key_pairs = { - "key": "ssh-keys", - "value": "" + key_data - } - self.logger.debug("generated keys: %s", key_data) - - metadata["items"].append(key_pairs) - """ self.logger.debug("metadata: %s", metadata) return metadata - def _generate_keys(self): - """Method used to generate a pair of private/public keys. - This method is used because to create a vm in Azure we always need a key or a password - In some cases we may have a password in a cloud-init file but it may not be available - """ - key = rsa.generate_private_key( - backend=crypto_default_backend(), public_exponent=65537, key_size=2048 - ) - private_key = key.private_bytes( - crypto_serialization.Encoding.PEM, - crypto_serialization.PrivateFormat.PKCS8, - crypto_serialization.NoEncryption(), - ) - public_key = key.public_key().public_bytes( - crypto_serialization.Encoding.OpenSSH, - crypto_serialization.PublicFormat.OpenSSH, - ) - private_key = private_key.decode("utf8") - # Change first line because Paramiko needs a explicit start with 'BEGIN RSA PRIVATE KEY' - i = private_key.find("\n") - private_key = "-----BEGIN RSA PRIVATE KEY-----" + private_key[i:] - public_key = public_key.decode("utf8") - - return private_key, public_key - - def _get_unused_vm_name(self, vm_name): - """ - Checks the vm name and in case it is used adds a suffix to the name to allow creation - :return: - """ - all_vms = ( - self.conn_compute.instances() - .list(project=self.project, zone=self.zone) - .execute() - ) - # Filter to vms starting with the indicated name - vms = list(filter(lambda vm: (vm.name.startswith(vm_name)), all_vms)) - vm_names = [str(vm.name) for vm in vms] - - # get the name with the first not used suffix - name_suffix = 0 - # name = subnet_name + "-" + str(name_suffix) - name = vm_name # first subnet created will have no prefix - - while name in vm_names: - name_suffix += 1 - name = vm_name + "-" + str(name_suffix) - - return name - def get_vminstance(self, vm_id): """ Obtaing the vm instance data from v_id @@ -1118,7 +1037,7 @@ class vimconnector(vimconn.VimConnector): self.logger.debug("get_vminstance Return: response %s", response) return response - def delete_vminstance(self, vm_id, created_items=None): + def delete_vminstance(self, vm_id, created_items=None, volumes_to_hold=None): """Deletes a vm instance from the vim.""" self.logger.debug( "delete_vminstance begin: vm_id %s created_items %s", @@ -1158,18 +1077,6 @@ class vimconnector(vimconn.VimConnector): else: self._format_vimconn_exception(e) - def _get_net_name_from_resource_id(self, resource_id): - try: - net_name = str(resource_id.split("/")[-1]) - - return net_name - except Exception: - raise vimconn.VimConnException( - "Unable to get google cloud net_name from invalid resource_id format '{}'".format( - resource_id - ) - ) - def _get_resource_name_from_resource_id(self, resource_id): """ Obtains resource_name from the google cloud complete identifier: resource_name will always be last item @@ -1193,6 +1100,20 @@ class vimconnector(vimconn.VimConnector): ) ) + def _get_id_from_image(self, image): + """ + Obtains image_id from the google cloud complete image identifier: image_id will be the last five items + """ + self.logger.debug(f"_get_id_from_image begin: image {image}") + try: + image_id = "/".join(image.split("/")[-5:]) + self.logger.debug(f"_get_id_from_image Return: image_id {image_id}") + return image_id + except Exception as e: + raise vimconn.VimConnException( + f"Unable to get image_id from image '{image}' Error: '{e}'" + ) + def refresh_nets_status(self, net_list): """Get the status of the networks Params: the list of network identifiers @@ -1287,7 +1208,43 @@ class vimconnector(vimconn.VimConnector): .execute() ) - out_vm["vim_info"] = str(vm["name"]) + disk_source = vm["disks"][0]["source"] + self.logger.debug("getting disk information") + disk = ( + self.conn_compute.disks() + .get( + project=self.project, + zone=self.zone, + disk=self._get_resource_name_from_resource_id(disk_source), + ) + .execute() + ) + image = {} + if disk is not None: + self.logger.debug(f"disk: {disk}") + image = { + "id": self._get_id_from_image(disk["sourceImage"]), + "source": disk_source, + } + + vim_info = { + "id": vm_id, + "name": vm["name"], + "creationTimestamp": vm["creationTimestamp"], + "lastStartTimestamp": vm["lastStartTimestamp"], + "vm_id": vm["id"], + "kind": vm["kind"], + "cpuPlatform": vm["cpuPlatform"], + "zone": self._get_resource_name_from_resource_id(vm["zone"]), + "machineType": vm["machineType"], + "flavor": { + "id": self._get_resource_name_from_resource_id( + vm["machineType"] + ) + }, + "image": image, + } + out_vm["vim_info"] = str(vim_info) out_vm["status"] = self.provision_state2osm.get(vm["status"], "OTHER") # In Google Cloud the there is no difference between provision or power status, @@ -1327,6 +1284,7 @@ class vimconnector(vimconn.VimConnector): for network_interface in interfaces: interface_dict = {} interface_dict["vim_interface_id"] = network_interface["name"] + interface_dict["vim_net_id"] = network_interface["subnetwork"] ips = [] ips.append(network_interface["networkIP"]) @@ -1347,12 +1305,6 @@ class vimconnector(vimconn.VimConnector): ) self._format_vimconn_exception(e) - def _get_default_admin_user(self, image_id): - if "ubuntu" in image_id.lower(): - return "ubuntu" - else: - return self._default_admin_user - def _create_firewall_rules(self, network): """ Creates the necessary firewall rules to allow the traffic in the network