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
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
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)
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)
)
try:
-
self.logger.debug("creating subnet_name: {}".format(subnet_name))
subnetwork_body = {
)
try:
-
if self.reload_client:
self._reload_connection()
self.logger.debug("Deleting network: {}".format(str(net_id)))
try:
-
net_name = self._get_resource_name_from_resource_id(net_id)
# Check associated VMs
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")
start,
image_id=None, # <image project>:(image|image-family):<image/family id>
flavor_id=None,
+ affinity_group_list=None,
net_list=None,
cloud_config=None,
disk_list=None,
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 (
# 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 "<key> <user@host>" into "<user>:<key>"
- 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
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",
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
)
)
+ 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
.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,
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"])
)
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
)
)
self._format_vimconn_exception(e)
+
+ def migrate_instance(self, vm_id, compute_host=None):
+ """
+ Migrate a vdu
+ param:
+ vm_id: ID of an instance
+ compute_host: Host to migrate the vdu to
+ """
+ # TODO: Add support for migration
+ raise vimconn.VimConnNotImplemented("Not implemented")
+
+ def resize_instance(self, vm_id, flavor_id=None):
+ """
+ resize a vdu
+ param:
+ vm_id: ID of an instance
+ flavor_id: flavor_id to resize the vdu to
+ """
+ # TODO: Add support for resize
+ raise vimconn.VimConnNotImplemented("Not implemented")