userdata = None
userdata_list = []
+ # For more information, check https://cloudinit.readthedocs.io/en/latest/reference/merging.html
+ # Basically, with this, we don't override the provider's cloud config
+ merge_how = yaml.safe_dump(
+ {
+ "merge_how": [
+ {
+ "name": "list",
+ "settings": ["append", "recurse_dict", "recurse_list"],
+ },
+ {
+ "name": "dict",
+ "settings": ["no_replace", "recurse_list", "recurse_dict"],
+ },
+ ]
+ },
+ indent=4,
+ default_flow_style=False,
+ )
+
if isinstance(cloud_config, dict):
if cloud_config.get("user-data"):
if isinstance(cloud_config["user-data"], str):
- userdata_list.append(cloud_config["user-data"])
+ userdata_list.append(cloud_config["user-data"] + f"\n{merge_how}")
else:
for u in cloud_config["user-data"]:
- userdata_list.append(u)
+ userdata_list.append(u + f"\n{merge_how}")
if cloud_config.get("boot-data-drive") is not None:
config_drive = cloud_config["boot-data-drive"]
# default user
if cloud_config.get("key-pairs"):
userdata_dict["ssh-authorized-keys"] = cloud_config["key-pairs"]
- userdata_dict["users"] = [
- {
- "default": None,
- "ssh-authorized-keys": cloud_config["key-pairs"],
+ userdata_dict["system_info"] = {
+ "default_user": {
+ "ssh_authorized_keys": cloud_config["key-pairs"],
}
- ]
+ }
+ userdata_dict["users"] = ["default"]
if cloud_config.get("users"):
if "users" not in userdata_dict:
userdata_list.append(
"#cloud-config\n"
+ yaml.safe_dump(userdata_dict, indent=4, default_flow_style=False)
+ + f"\n{merge_how}"
)
userdata = self._create_mimemultipart(userdata_list)
self.logger.debug("userdata: %s", userdata)
"""Returns the VM instance information from VIM"""
raise VimConnNotImplemented("Should have implemented this")
- def delete_vminstance(self, vm_id, created_items=None):
+ def delete_vminstance(self, vm_id, created_items=None, volumes_to_hold=None):
"""
Removes a VM instance from VIM and its associated elements
:param vm_id: VIM identifier of the VM, provided by method new_vminstance
"chmod 644 ~/.ssh/authorized_keys",
"chmod 700 ~/.ssh/",
}
+
+ logging.basicConfig(
+ format="%(asctime)s %(levelname)s %(name)s %(filename)s:%(lineno)s %(message)s"
+ )
+ logging.getLogger("paramiko").setLevel(logging.DEBUG)
client = paramiko.SSHClient()
try:
pkey = None
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+
client.connect(
- ip_addr, username=user, password=password, pkey=pkey, timeout=30
+ ip_addr,
+ username=user,
+ password=password,
+ pkey=pkey,
+ timeout=30,
+ auth_timeout=60,
)
for command in commands:
"""
raise VimConnNotImplemented("Should have implemented this")
- def new_classification(self, name, ctype, definition):
- """Creates a traffic classification in the VIM
- Params:
- 'name': name of this classification
- 'ctype': type of this classification
- 'definition': definition of this classification (type-dependent free-form text)
- Returns the VIM's classification ID on success or raises an exception on failure
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def get_classification(self, classification_id):
- """Obtain classification details of the VIM's classification with ID='classification_id'
- Return a dict that contains:
- 'id': VIM's classification ID (same as classification_id)
- 'name': VIM's classification name
- 'type': type of this classification
- 'definition': definition of the classification
- 'status': 'ACTIVE', 'INACTIVE', 'DOWN', 'BUILD', 'ERROR', 'VIM_ERROR', 'OTHER'
- 'error_msg': (optional) text that explains the ERROR status
- other VIM specific fields: (optional) whenever possible
- Raises an exception upon error or when classification is not found
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def get_classification_list(self, filter_dict={}):
- """Obtain classifications from the VIM
- Params:
- 'filter_dict' (optional): contains the entries to filter the classifications on and only return those that
- match ALL:
- id: string => returns classifications with this VIM's classification ID, which implies a return of one
- classification at most
- name: string => returns only classifications with this name
- type: string => returns classifications of this type
- definition: string => returns classifications that have this definition
- tenant_id: string => returns only classifications that belong to this tenant/project
- Returns a list of classification dictionaries, each dictionary contains:
- 'id': (mandatory) VIM's classification ID
- 'name': (mandatory) VIM's classification name
- 'type': type of this classification
- 'definition': definition of the classification
- other VIM specific fields: (optional) whenever possible using the same naming of filter_dict param
- List can be empty if no classification matches the filter_dict. Raise an exception only upon VIM connectivity,
- authorization, or some other unspecific error
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def refresh_classifications_status(self, classification_list):
- """Get the status of the classifications
- Params: the list of classification identifiers
- Returns a dictionary with:
- vm_id: #VIM id of this classifier
- status: #Mandatory. Text with one of:
- # DELETED (not found at vim)
- # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
- # OTHER (Vim reported other status not understood)
- # ERROR (VIM indicates an ERROR status)
- # ACTIVE,
- # CREATING (on building process)
- error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
- vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
- """
- raise VimConnNotImplemented("Should have implemented this")
-
- def delete_classification(self, classification_id):
- """Deletes a classification from the VIM
- Returns the classification ID (classification_id) or raises an exception upon error or when classification is
- not found
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def new_sfi(self, name, ingress_ports, egress_ports, sfc_encap=True):
- """Creates a service function instance in the VIM
- Params:
- 'name': name of this service function instance
- 'ingress_ports': set of ingress ports (VIM's port IDs)
- 'egress_ports': set of egress ports (VIM's port IDs)
- 'sfc_encap': boolean stating whether this specific instance supports IETF SFC Encapsulation
- Returns the VIM's service function instance ID on success or raises an exception on failure
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def get_sfi(self, sfi_id):
- """Obtain service function instance details of the VIM's service function instance with ID='sfi_id'
- Return a dict that contains:
- 'id': VIM's sfi ID (same as sfi_id)
- 'name': VIM's sfi name
- 'ingress_ports': set of ingress ports (VIM's port IDs)
- 'egress_ports': set of egress ports (VIM's port IDs)
- 'status': 'ACTIVE', 'INACTIVE', 'DOWN', 'BUILD', 'ERROR', 'VIM_ERROR', 'OTHER'
- 'error_msg': (optional) text that explains the ERROR status
- other VIM specific fields: (optional) whenever possible
- Raises an exception upon error or when service function instance is not found
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def get_sfi_list(self, filter_dict={}):
- """Obtain service function instances from the VIM
- Params:
- 'filter_dict' (optional): contains the entries to filter the sfis on and only return those that match ALL:
- id: string => returns sfis with this VIM's sfi ID, which implies a return of one sfi at most
- name: string => returns only service function instances with this name
- tenant_id: string => returns only service function instances that belong to this tenant/project
- Returns a list of service function instance dictionaries, each dictionary contains:
- 'id': (mandatory) VIM's sfi ID
- 'name': (mandatory) VIM's sfi name
- 'ingress_ports': set of ingress ports (VIM's port IDs)
- 'egress_ports': set of egress ports (VIM's port IDs)
- other VIM specific fields: (optional) whenever possible using the same naming of filter_dict param
- List can be empty if no sfi matches the filter_dict. Raise an exception only upon VIM connectivity,
- authorization, or some other unspecific error
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def delete_sfi(self, sfi_id):
- """Deletes a service function instance from the VIM
- Returns the service function instance ID (sfi_id) or raises an exception upon error or when sfi is not found
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def refresh_sfis_status(self, sfi_list):
- """Get the status of the service function instances
- Params: the list of sfi identifiers
- Returns a dictionary with:
- vm_id: #VIM id of this service function instance
- status: #Mandatory. Text with one of:
- # DELETED (not found at vim)
- # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
- # OTHER (Vim reported other status not understood)
- # ERROR (VIM indicates an ERROR status)
- # ACTIVE,
- # CREATING (on building process)
- error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
- vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
- """
- raise VimConnNotImplemented("Should have implemented this")
-
- def new_sf(self, name, sfis, sfc_encap=True):
- """Creates (an abstract) service function in the VIM
- Params:
- 'name': name of this service function
- 'sfis': set of service function instances of this (abstract) service function
- 'sfc_encap': boolean stating whether this service function supports IETF SFC Encapsulation
- Returns the VIM's service function ID on success or raises an exception on failure
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def get_sf(self, sf_id):
- """Obtain service function details of the VIM's service function with ID='sf_id'
- Return a dict that contains:
- 'id': VIM's sf ID (same as sf_id)
- 'name': VIM's sf name
- 'sfis': VIM's sf's set of VIM's service function instance IDs
- 'sfc_encap': boolean stating whether this service function supports IETF SFC Encapsulation
- 'status': 'ACTIVE', 'INACTIVE', 'DOWN', 'BUILD', 'ERROR', 'VIM_ERROR', 'OTHER'
- 'error_msg': (optional) text that explains the ERROR status
- other VIM specific fields: (optional) whenever possible
- Raises an exception upon error or when sf is not found
- """
-
- def get_sf_list(self, filter_dict={}):
- """Obtain service functions from the VIM
- Params:
- 'filter_dict' (optional): contains the entries to filter the sfs on and only return those that match ALL:
- id: string => returns sfs with this VIM's sf ID, which implies a return of one sf at most
- name: string => returns only service functions with this name
- tenant_id: string => returns only service functions that belong to this tenant/project
- Returns a list of service function dictionaries, each dictionary contains:
- 'id': (mandatory) VIM's sf ID
- 'name': (mandatory) VIM's sf name
- 'sfis': VIM's sf's set of VIM's service function instance IDs
- 'sfc_encap': boolean stating whether this service function supports IETF SFC Encapsulation
- other VIM specific fields: (optional) whenever possible using the same naming of filter_dict param
- List can be empty if no sf matches the filter_dict. Raise an exception only upon VIM connectivity,
- authorization, or some other unspecific error
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def delete_sf(self, sf_id):
- """Deletes (an abstract) service function from the VIM
- Returns the service function ID (sf_id) or raises an exception upon error or when sf is not found
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def refresh_sfs_status(self, sf_list):
- """Get the status of the service functions
- Params: the list of sf identifiers
- Returns a dictionary with:
- vm_id: #VIM id of this service function
- status: #Mandatory. Text with one of:
- # DELETED (not found at vim)
- # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
- # OTHER (Vim reported other status not understood)
- # ERROR (VIM indicates an ERROR status)
- # ACTIVE,
- # CREATING (on building process)
- error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
- vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
- """
- raise VimConnNotImplemented("Should have implemented this")
-
- def new_sfp(self, name, classifications, sfs, sfc_encap=True, spi=None):
- """Creates a service function path
- Params:
- 'name': name of this service function path
- 'classifications': set of traffic classifications that should be matched on to get into this sfp
- 'sfs': list of every service function that constitutes this path , from first to last
- 'sfc_encap': whether this is an SFC-Encapsulated chain (i.e using NSH), True by default
- 'spi': (optional) the Service Function Path identifier (SPI: Service Path Identifier) for this path
- Returns the VIM's sfp ID on success or raises an exception on failure
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def get_sfp(self, sfp_id):
- """Obtain service function path details of the VIM's sfp with ID='sfp_id'
- Return a dict that contains:
- 'id': VIM's sfp ID (same as sfp_id)
- 'name': VIM's sfp name
- 'classifications': VIM's sfp's list of VIM's classification IDs
- 'sfs': VIM's sfp's list of VIM's service function IDs
- 'status': 'ACTIVE', 'INACTIVE', 'DOWN', 'BUILD', 'ERROR', 'VIM_ERROR', 'OTHER'
- 'error_msg': (optional) text that explains the ERROR status
- other VIM specific fields: (optional) whenever possible
- Raises an exception upon error or when sfp is not found
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def get_sfp_list(self, filter_dict={}):
- """Obtain service function paths from VIM
- Params:
- 'filter_dict' (optional): contains the entries to filter the sfps on, and only return those that match ALL:
- id: string => returns sfps with this VIM's sfp ID , which implies a return of one sfp at most
- name: string => returns only sfps with this name
- tenant_id: string => returns only sfps that belong to this tenant/project
- Returns a list of service function path dictionaries, each dictionary contains:
- 'id': (mandatory) VIM's sfp ID
- 'name': (mandatory) VIM's sfp name
- 'classifications': VIM's sfp's list of VIM's classification IDs
- 'sfs': VIM's sfp's list of VIM's service function IDs
- other VIM specific fields: (optional) whenever possible using the same naming of filter_dict param
- List can be empty if no sfp matches the filter_dict. Raise an exception only upon VIM connectivity,
- authorization, or some other unspecific error
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
- def refresh_sfps_status(self, sfp_list):
- """Get the status of the service function path
- Params: the list of sfp identifiers
- Returns a dictionary with:
- vm_id: #VIM id of this service function path
- status: #Mandatory. Text with one of:
- # DELETED (not found at vim)
- # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
- # OTHER (Vim reported other status not understood)
- # ERROR (VIM indicates an ERROR status)
- # ACTIVE,
- # CREATING (on building process)
- error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
- vim_info: #Text with plain information obtained from vim (yaml.safe_dump)F
- """
- raise VimConnNotImplemented("Should have implemented this")
-
- def delete_sfp(self, sfp_id):
- """Deletes a service function path from the VIM
- Returns the sfp ID (sfp_id) or raises an exception upon error or when sf is not found
- """
- raise VimConnNotImplemented("SFC support not implemented")
-
def migrate_instance(self, vm_id, compute_host=None):
"""Migrate a vdu
Params:
"""
raise VimConnNotImplemented("Should have implemented this")
- # NOT USED METHODS in current version. Deprecated
- @deprecated
- def host_vim2gui(self, host, server_dict):
- """Transform host dictionary from VIM format to GUI format,
- and append to the server_dict
+ 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
"""
- raise VimConnNotImplemented("Should have implemented this")
-
- @deprecated
- def get_hosts_info(self):
- """Get the information of deployed hosts
- Returns the hosts content"""
- raise VimConnNotImplemented("Should have implemented this")
-
- @deprecated
- def get_hosts(self, vim_tenant):
- """Get the hosts and deployed instances
- Returns the hosts content"""
- raise VimConnNotImplemented("Should have implemented this")
-
- @deprecated
- def get_processor_rankings(self):
- """Get the processor rankings in the VIM database"""
- raise VimConnNotImplemented("Should have implemented this")
-
- @deprecated
- def new_host(self, host_data):
- """Adds a new host to VIM"""
- """Returns status code of the VIM response"""
- raise VimConnNotImplemented("Should have implemented this")
-
- @deprecated
- def new_external_port(self, port_data):
- """Adds a external port to VIM"""
- """Returns the port identifier"""
- raise VimConnNotImplemented("Should have implemented this")
-
- @deprecated
- def new_external_network(self, net_name, net_type):
- """Adds a external network to VIM (shared)"""
- """Returns the network identifier"""
- raise VimConnNotImplemented("Should have implemented this")
-
- @deprecated
- def connect_port_network(self, port_id, network_id, admin=False):
- """Connects a external port to a network"""
- """Returns status code of the VIM response"""
- raise VimConnNotImplemented("Should have implemented this")
-
- @deprecated
- def new_vminstancefromJSON(self, vm_data):
- """Adds a VM instance to VIM"""
- """Returns the instance identifier"""
raise VimConnNotImplemented("Should have implemented this")