X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=snaps%2Fopenstack%2Fcreate_instance.py;h=0105ef08e760178939e1ea4035af8483797a4088;hb=e2f708a2527816a845ca1048f5ad5c58fdb506e0;hp=c970a3113a1361c3ba6bde6a80edabef43e16c06;hpb=e6326cd5e826d19e4dd2b096c17aff35da1757b3;p=snaps.git diff --git a/snaps/openstack/create_instance.py b/snaps/openstack/create_instance.py index c970a31..0105ef0 100644 --- a/snaps/openstack/create_instance.py +++ b/snaps/openstack/create_instance.py @@ -16,12 +16,14 @@ import logging import time from neutronclient.common.exceptions import PortNotFoundClient -from novaclient.exceptions import NotFound +from novaclient.exceptions import NotFound, BadRequest -from snaps.openstack.create_network import PortSettings -from snaps.openstack.utils import glance_utils +from snaps.config.vm_inst import VmInstanceConfig, FloatingIpConfig +from snaps.openstack.openstack_creator import OpenStackComputeObject +from snaps.openstack.utils import glance_utils, cinder_utils, settings_utils from snaps.openstack.utils import neutron_utils from snaps.openstack.utils import nova_utils +from snaps.openstack.utils.nova_utils import RebootType from snaps.provisioning import ansible_utils __author__ = 'spisarski' @@ -33,9 +35,9 @@ STATUS_ACTIVE = 'ACTIVE' STATUS_DELETED = 'DELETED' -class OpenStackVmInstance: +class OpenStackVmInstance(OpenStackComputeObject): """ - Class responsible for creating a VM instance in OpenStack + Class responsible for managing a VM instance in OpenStack """ def __init__(self, os_creds, instance_settings, image_settings, @@ -48,18 +50,14 @@ class OpenStackVmInstance: :param keypair_settings: The keypair metadata (Optional) :raises Exception """ - self.__os_creds = os_creds + super(self.__class__, self).__init__(os_creds) - self.__nova = None self.__neutron = None self.instance_settings = instance_settings self.image_settings = image_settings self.keypair_settings = keypair_settings - # TODO - get rid of FIP list and only use the dict(). Need to fix - # populating this object when already exists - self.__floating_ips = list() self.__floating_ip_dict = dict() # Instantiated in self.create() @@ -68,24 +66,35 @@ class OpenStackVmInstance: # Note: this object does not change after the VM becomes active self.__vm = None - def create(self, cleanup=False, block=False): + def initialize(self): """ - Creates a VM instance - :param cleanup: When true, only perform lookups for OpenStack objects. + Loads the existing VMInst, Port, FloatingIps + :return: VMInst domain object + """ + super(self.__class__, self).initialize() + + self.__neutron = neutron_utils.neutron_client(self._os_creds) + + self.__ports = self.__query_ports(self.instance_settings.port_settings) + self.__lookup_existing_vm_by_name() + + def create(self, block=False): + """ + Creates a VM instance and associated objects unless they already exist :param block: Thread will block until instance has either become active, error, or timeout waiting. Additionally, when True, floating IPs will not be applied until VM is active. - :return: The VM reference object + :return: VMInst domain object """ - self.__nova = nova_utils.nova_client(self.__os_creds) - self.__neutron = neutron_utils.neutron_client(self.__os_creds) + self.initialize() - self.__ports = self.__setup_ports(self.instance_settings.port_settings, - cleanup) - self.__lookup_existing_vm_by_name() - if not self.__vm and not cleanup: + if len(self.__ports) == 0: + self.__ports = self.__create_ports( + self.instance_settings.port_settings) + if not self.__vm: self.__create_vm(block) + return self.__vm def __lookup_existing_vm_by_name(self): @@ -94,21 +103,27 @@ class OpenStackVmInstance: VM with the same name already exists within the project """ - servers = nova_utils.get_servers_by_name(self.__nova, - self.instance_settings.name) - for server in servers: + server = nova_utils.get_server( + self._nova, vm_inst_settings=self.instance_settings) + if server: if server.name == self.instance_settings.name: self.__vm = server logger.info( 'Found existing machine with name - %s', self.instance_settings.name) - fips = neutron_utils.get_floating_ips(self.__neutron) - for fip in fips: - for subnet_name, ips in server.networks.items(): - if fip.ip in ips: - self.__floating_ips.append(fip) - # TODO - Determine a means to associate to the FIP - # configuration and add to FIP map + + fips = neutron_utils.get_floating_ips(self.__neutron, + self.__ports) + for port_id, fip in fips: + settings = self.instance_settings.floating_ip_settings + for fip_setting in settings: + if port_id == fip_setting.port_id: + self.__floating_ip_dict[fip_setting.name] = fip + else: + port = neutron_utils.get_port_by_id( + self.__neutron, port_id) + if port and port.name == fip_setting.port_name: + self.__floating_ip_dict[fip_setting.name] = fip def __create_vm(self, block=False): """ @@ -117,31 +132,51 @@ class OpenStackVmInstance: active, error, or timeout waiting. Floating IPs will be assigned after active when block=True """ - glance = glance_utils.glance_client(self.__os_creds) + glance = glance_utils.glance_client(self._os_creds) self.__vm = nova_utils.create_server( - self.__nova, self.__neutron, glance, self.instance_settings, + self._nova, self.__neutron, glance, self.instance_settings, self.image_settings, self.keypair_settings) logger.info('Created instance with name - %s', self.instance_settings.name) if block: if not self.vm_active(block=True): - raise Exception( + raise VmInstanceCreationError( 'Fatal error, VM did not become ACTIVE within the alloted ' 'time') # Create server should do this but found it needed to occur here for sec_grp_name in self.instance_settings.security_group_names: if self.vm_active(block=True): - nova_utils.add_security_group(self.__nova, self.__vm, + nova_utils.add_security_group(self._nova, self.__vm, sec_grp_name) else: - raise Exception( + raise VmInstanceCreationError( 'Cannot applying security group with name ' + sec_grp_name + ' to VM that did not activate with name - ' + self.instance_settings.name) + if self.instance_settings.volume_names: + for volume_name in self.instance_settings.volume_names: + cinder = cinder_utils.cinder_client(self._os_creds) + volume = cinder_utils.get_volume( + cinder, volume_name=volume_name) + + if volume and self.vm_active(block=True): + timeout = 30 + vm = nova_utils.attach_volume( + self._nova, self.__vm, volume, timeout) + + if vm: + self.__vm = vm + else: + logger.warn('Volume [%s] not attached within timeout ' + 'of [%s]', volume.name, timeout) + else: + logger.warn('Unable to attach volume named [%s]', + volume_name) + self.__apply_floating_ips() def __apply_floating_ips(self): @@ -154,33 +189,45 @@ class OpenStackVmInstance: # Apply floating IPs for floating_ip_setting in self.instance_settings.floating_ip_settings: - port = port_dict.get(floating_ip_setting.port_name) + self.add_floating_ip(floating_ip_setting) - if not port: - raise Exception( - 'Cannot find port object with name - ' + - floating_ip_setting.port_name) + def add_floating_ip(self, floating_ip_setting): + """ + Adds a floating IP to a running instance + :param floating_ip_setting - the floating IP configuration + """ + port_dict = dict() + for key, port in self.__ports: + port_dict[key] = port - # Setup Floating IP only if there is a router with an external - # gateway - ext_gateway = self.__ext_gateway_by_router( - floating_ip_setting.router_name) - if ext_gateway: - subnet = neutron_utils.get_subnet_by_name( - self.__neutron, floating_ip_setting.subnet_name) - floating_ip = neutron_utils.create_floating_ip( - self.__neutron, ext_gateway) - self.__floating_ips.append(floating_ip) - self.__floating_ip_dict[floating_ip_setting.name] = floating_ip + # Apply floating IP + port = port_dict.get(floating_ip_setting.port_name) - logger.info( - 'Created floating IP %s via router - %s', floating_ip.ip, - floating_ip_setting.router_name) - self.__add_floating_ip(floating_ip, port, subnet) - else: - raise Exception('Unable to add floating IP to port,' - ' cannot locate router with an external ' - 'gateway ') + if not port: + raise VmInstanceCreationError( + 'Cannot find port object with name - ' + + floating_ip_setting.port_name) + + # Setup Floating IP only if there is a router with an external + # gateway + ext_gateway = self.__ext_gateway_by_router( + floating_ip_setting.router_name) + if ext_gateway: + subnet = neutron_utils.get_subnet( + self.__neutron, + subnet_name=floating_ip_setting.subnet_name) + floating_ip = neutron_utils.create_floating_ip( + self.__neutron, ext_gateway) + self.__floating_ip_dict[floating_ip_setting.name] = floating_ip + + logger.info( + 'Created floating IP %s via router - %s', floating_ip.ip, + floating_ip_setting.router_name) + self.__add_floating_ip(floating_ip, port, subnet) + else: + raise VmInstanceCreationError( + 'Unable to add floating IP to port, cannot locate router ' + 'with an external gateway ') def __ext_gateway_by_router(self, router_name): """ @@ -189,13 +236,13 @@ class OpenStackVmInstance: :param router_name: The name of the router to lookup :return: the external network name or None """ - router = neutron_utils.get_router_by_name(self.__neutron, router_name) - if router and router['router'].get('external_gateway_info'): + router = neutron_utils.get_router( + self.__neutron, router_name=router_name) + if router and router.external_network_id: network = neutron_utils.get_network_by_id( - self.__neutron, - router['router']['external_gateway_info']['network_id']) + self.__neutron, router.external_network_id) if network: - return network['network']['name'] + return network.name return None def clean(self): @@ -204,18 +251,37 @@ class OpenStackVmInstance: """ # Cleanup floating IPs - for floating_ip in self.__floating_ips: + for name, floating_ip in self.__floating_ip_dict.items(): try: logger.info('Deleting Floating IP - ' + floating_ip.ip) neutron_utils.delete_floating_ip(self.__neutron, floating_ip) except Exception as e: logger.error('Error deleting Floating IP - ' + str(e)) - self.__floating_ips = list() self.__floating_ip_dict = dict() + # Detach Volume + for volume_rec in self.__vm.volume_ids: + cinder = cinder_utils.cinder_client(self._os_creds) + volume = cinder_utils.get_volume_by_id(cinder, volume_rec['id']) + if volume: + try: + vm = nova_utils.detach_volume( + self._nova, self.__vm, volume, 30) + if vm: + self.__vm = vm + else: + logger.warn( + 'Timeout waiting to detach volume %s', volume.name) + except Exception as e: + logger.error('Unexpected error detaching volume %s ' + 'with error %s', volume.name, e) + else: + logger.warn('Unable to detach volume with ID - [%s]', + volume_rec['id']) + # Cleanup ports for name, port in self.__ports: - logger.info('Deleting Port - ' + name) + logger.info('Deleting Port with ID - %s ', port.id) try: neutron_utils.delete_port(self.__neutron, port) except PortNotFoundClient as e: @@ -228,7 +294,7 @@ class OpenStackVmInstance: try: logger.info( 'Deleting VM instance - ' + self.instance_settings.name) - nova_utils.delete_vm_instance(self.__nova, self.__vm) + nova_utils.delete_vm_instance(self._nova, self.__vm) except Exception as e: logger.error('Error deleting VM - %s', e) @@ -251,39 +317,42 @@ class OpenStackVmInstance: 'Unexpected error while checking VM instance status - %s', e) - def __setup_ports(self, port_settings, cleanup): + def __query_ports(self, port_settings): """ - Returns the previously configured ports or creates them if they do not + Returns the previously configured ports or an empty list if none exist :param port_settings: A list of PortSetting objects - :param cleanup: When true, only perform lookups for OpenStack objects. :return: a list of OpenStack port tuples where the first member is the port name and the second is the port object """ ports = list() for port_setting in port_settings: - # First check to see if network already has this port - # TODO/FIXME - this could potentially cause problems if another - # port with the same name exists - # VM has the same network/port name pair - found = False - - # TODO/FIXME - should we not be iterating on ports for the specific - # network in question as unique port names - # seem to only be important by network - existing_ports = self.__neutron.list_ports()['ports'] - for existing_port in existing_ports: - if existing_port['name'] == port_setting.name: - ports.append((port_setting.name, {'port': existing_port})) - found = True - break + port = neutron_utils.get_port( + self.__neutron, port_settings=port_setting) + if port: + ports.append((port_setting.name, port)) + + return ports - if not found and not cleanup: - ports.append((port_setting.name, - neutron_utils.create_port(self.__neutron, - self.__os_creds, - port_setting))) + def __create_ports(self, port_settings): + """ + Returns the previously configured ports or creates them if they do not + exist + :param port_settings: A list of PortSetting objects + :return: a list of OpenStack port tuples where the first member is the + port name and the second is the port object + """ + ports = list() + + for port_setting in port_settings: + port = neutron_utils.get_port( + self.__neutron, port_settings=port_setting) + if not port: + port = neutron_utils.create_port( + self.__neutron, self._os_creds, port_setting) + if port: + ports.append((port_setting.name, port)) return ports @@ -298,8 +367,8 @@ class OpenStackVmInstance: if subnet: # Take IP of subnet if there is one configured on which to place # the floating IP - for fixed_ip in port.fixed_ips: - if fixed_ip['subnet_id'] == subnet['subnet']['id']: + for fixed_ip in port.ips: + if fixed_ip['subnet_id'] == subnet.id: ip = fixed_ip['ip_address'] break else: @@ -312,11 +381,14 @@ class OpenStackVmInstance: logger.debug('Attempting to add floating IP to instance') try: nova_utils.add_floating_ip_to_server( - self.__nova, self.__vm, floating_ip, ip) + self._nova, self.__vm, floating_ip, ip) logger.info( 'Added floating IP %s to port IP %s on instance %s', floating_ip.ip, ip, self.instance_settings.name) return + except BadRequest as bre: + logger.error('Cannot add floating IP [%s]', bre) + raise except Exception as e: logger.debug( 'Retry adding floating IP to instance. Last attempt ' @@ -325,32 +397,33 @@ class OpenStackVmInstance: count -= 1 pass else: - raise Exception( + raise VmInstanceCreationError( 'Unable find IP address on which to place the floating IP') logger.error('Timeout attempting to add the floating IP to instance.') - raise Exception('Timeout while attempting add floating IP to instance') + raise VmInstanceCreationError( + 'Timeout while attempting add floating IP to instance') def get_os_creds(self): """ Returns the OpenStack credentials used to create these objects :return: the credentials """ - return self.__os_creds + return self._os_creds def get_vm_inst(self): """ Returns the latest version of this server object from OpenStack :return: Server object """ - return self.__vm + return nova_utils.get_server_object_by_id(self._nova, self.__vm.id) - def get_os_vm_server_obj(self): + def get_console_output(self): """ - Returns the OpenStack server object - :return: the server object + Returns the vm console object for parsing logs + :return: the console output object """ - return nova_utils.get_latest_server_os_object(self.__nova, self.__vm) + return nova_utils.get_server_console_output(self._nova, self.__vm) def get_port_ip(self, port_name, subnet_name=None): """ @@ -364,15 +437,15 @@ class OpenStackVmInstance: port = self.get_port_by_name(port_name) if port: if subnet_name: - subnet = neutron_utils.get_subnet_by_name(self.__neutron, - subnet_name) + subnet = neutron_utils.get_subnet( + self.__neutron, subnet_name=subnet_name) if not subnet: logger.warning('Cannot retrieve port IP as subnet could ' 'not be located with name - %s', subnet_name) return None for fixed_ip in port.ips: - if fixed_ip['subnet_id'] == subnet['subnet']['id']: + if fixed_ip['subnet_id'] == subnet.id: return fixed_ip['ip_address'] else: if port.ips and len(port.ips) > 0: @@ -405,23 +478,31 @@ class OpenStackVmInstance: logger.warning('Cannot find port with name - ' + port_name) return None + def get_vm_info(self): + """ + Returns a dictionary of a VMs info as returned by OpenStack + :return: a dict() + """ + return nova_utils.get_server_info(self._nova, self.__vm) + def config_nics(self): """ Responsible for configuring NICs on RPM systems where the instance has more than one configured port - :return: None + :return: the value returned by ansible_utils.apply_ansible_playbook() """ - if len(self.__ports) > 1 and len(self.__floating_ips) > 0: + if len(self.__ports) > 1 and len(self.__floating_ip_dict) > 0: if self.vm_active(block=True) and self.vm_ssh_active(block=True): for key, port in self.__ports: port_index = self.__ports.index((key, port)) if port_index > 0: nic_name = 'eth' + repr(port_index) - self.__config_nic( + retval = self.__config_nic( nic_name, port, self.__get_first_provisioning_floating_ip().ip) logger.info('Configured NIC - %s on VM - %s', nic_name, self.instance_settings.name) + return retval def __get_first_provisioning_floating_ip(self): """ @@ -434,8 +515,14 @@ class OpenStackVmInstance: fip = self.__floating_ip_dict.get(floating_ip_setting.name) if fip: return fip - elif len(self.__floating_ips) > 0: - return self.__floating_ips[0] + elif len(self.__floating_ip_dict) > 0: + for key, fip in self.__floating_ip_dict.items(): + return fip + + # When cannot be found above + if len(self.__floating_ip_dict) > 0: + for key, fip in self.__floating_ip_dict.items(): + return fip def __config_nic(self, nic_name, port, ip): """ @@ -476,7 +563,7 @@ class OpenStackVmInstance: return ansible_utils.apply_playbook( pb_file_loc, [self.get_floating_ip(fip_name=fip_name).ip], self.get_image_user(), self.keypair_settings.private_filepath, - variables, self.__os_creds.proxy_settings) + variables, self._os_creds.proxy_settings) def get_image_user(self): """ @@ -509,16 +596,20 @@ class OpenStackVmInstance: def vm_active(self, block=False, poll_interval=POLL_INTERVAL): """ - Returns true when the VM status returns the value of - expected_status_code + Returns true when the VM status returns the value of the constant + STATUS_ACTIVE :param block: When true, thread will block until active or timeout value in seconds has been exceeded (False) :param poll_interval: The polling interval in seconds :return: T/F """ - return self.__vm_status_check(STATUS_ACTIVE, block, - self.instance_settings.vm_boot_timeout, - poll_interval) + if self.__vm_status_check( + STATUS_ACTIVE, block, self.instance_settings.vm_boot_timeout, + poll_interval): + self.__vm = nova_utils.get_server_object_by_id( + self._nova, self.__vm.id) + return True + return False def __vm_status_check(self, expected_status_code, block, timeout, poll_interval): @@ -563,20 +654,23 @@ class OpenStackVmInstance: :return: T/F """ if not self.__vm: - return False + if expected_status_code == STATUS_DELETED: + return True + else: + return False - instance = nova_utils.get_latest_server_os_object( - self.__nova, self.__vm) - if not instance: + status = nova_utils.get_server_status(self._nova, self.__vm) + if not status: logger.warning('Cannot find instance with id - ' + self.__vm.id) return False - if instance.status == 'ERROR': - raise Exception('Instance had an error during deployment') + if status == 'ERROR': + raise VmInstanceCreationError( + 'Instance had an error during deployment') logger.debug( 'Instance status [%s] is - %s', self.instance_settings.name, - instance.status) - return instance.status == expected_status_code + status) + return status == expected_status_code def vm_ssh_active(self, block=False, poll_interval=POLL_INTERVAL): """ @@ -617,9 +711,10 @@ class OpenStackVmInstance: Returns True when can create a SSH session else False :return: T/F """ - if len(self.__floating_ips) > 0: + if len(self.__floating_ip_dict) > 0: ssh = self.ssh_client() if ssh: + ssh.close() return True return False @@ -630,12 +725,10 @@ class OpenStackVmInstance: :param fip_name: the name of the floating IP to return :return: the SSH client or None """ - fip = None if fip_name and self.__floating_ip_dict.get(fip_name): return self.__floating_ip_dict.get(fip_name) - if not fip and len(self.__floating_ips) > 0: - return self.__floating_ips[0] - return None + else: + return self.__get_first_provisioning_floating_ip() def ssh_client(self, fip_name=None): """ @@ -647,11 +740,12 @@ class OpenStackVmInstance: fip = self.get_floating_ip(fip_name) if fip: return ansible_utils.ssh_client( - self.__floating_ips[0].ip, self.get_image_user(), + self.__get_first_provisioning_floating_ip().ip, + self.get_image_user(), self.keypair_settings.private_filepath, - proxy_settings=self.__os_creds.proxy_settings) + proxy_settings=self._os_creds.proxy_settings) else: - logger.warning( + FloatingIPAllocationError( 'Cannot return an SSH client. No Floating IP configured') def add_security_group(self, security_group): @@ -667,7 +761,7 @@ class OpenStackVmInstance: return False try: - nova_utils.add_security_group(self.__nova, self.get_vm_inst(), + nova_utils.add_security_group(self._nova, self.get_vm_inst(), security_group.name) return True except NotFound as e: @@ -687,145 +781,74 @@ class OpenStackVmInstance: return False try: - nova_utils.remove_security_group(self.__nova, self.get_vm_inst(), + nova_utils.remove_security_group(self._nova, self.get_vm_inst(), security_group) return True except NotFound as e: logger.warning('Security group not removed - ' + str(e)) return False + def reboot(self, reboot_type=RebootType.soft): + """ + Issues a reboot call + :param reboot_type: instance of + snaps.openstack.utils.nova_utils.RebootType + enumeration + :return: + """ + nova_utils.reboot_server( + self._nova, self.__vm, reboot_type=reboot_type) + -class VmInstanceSettings: +def generate_creator(os_creds, vm_inst, image_config, keypair_config=None): """ - Class responsible for holding configuration setting for a VM Instance + Initializes an OpenStackVmInstance object + :param os_creds: the OpenStack credentials + :param vm_inst: the SNAPS-OO VmInst domain object + :param image_config: the associated ImageConfig object + :param keypair_config: the associated KeypairConfig object (optional) + :return: an initialized OpenStackVmInstance object """ + nova = nova_utils.nova_client(os_creds) + neutron = neutron_utils.neutron_client(os_creds) + derived_inst_config = settings_utils.create_vm_inst_config( + nova, neutron, vm_inst) - def __init__(self, **kwargs): - """ - Constructor - :param name: the name of the VM - :param flavor: the VM's flavor - :param port_settings: the port configuration settings (required) - :param security_group_names: a set of names of the security groups to - add to the VM - :param floating_ip_settings: the floating IP configuration settings - :param sudo_user: the sudo user of the VM that will override the - instance_settings.image_user when trying to - connect to the VM - :param vm_boot_timeout: the amount of time a thread will sleep waiting - for an instance to boot - :param vm_delete_timeout: the amount of time a thread will sleep - waiting for an instance to be deleted - :param ssh_connect_timeout: the amount of time a thread will sleep - waiting obtaining an SSH connection to a VM - :param availability_zone: the name of the compute server on which to - deploy the VM (optional) - :param userdata: the cloud-init script to run after the VM has been - started - """ - self.name = kwargs.get('name') - self.flavor = kwargs.get('flavor') - self.sudo_user = kwargs.get('sudo_user') - self.userdata = kwargs.get('userdata') - - self.port_settings = list() - port_settings = kwargs.get('ports') - if not port_settings: - port_settings = kwargs.get('port_settings') - if port_settings: - for port_setting in port_settings: - if isinstance(port_setting, dict): - self.port_settings.append(PortSettings(**port_setting)) - elif isinstance(port_setting, PortSettings): - self.port_settings.append(port_setting) - - if kwargs.get('security_group_names'): - if isinstance(kwargs['security_group_names'], list): - self.security_group_names = kwargs['security_group_names'] - elif isinstance(kwargs['security_group_names'], set): - self.security_group_names = kwargs['security_group_names'] - elif isinstance(kwargs['security_group_names'], str): - self.security_group_names = [kwargs['security_group_names']] - else: - raise Exception( - 'Invalid data type for security_group_names attribute') - else: - self.security_group_names = set() - - self.floating_ip_settings = list() - floating_ip_settings = kwargs.get('floating_ips') - if not floating_ip_settings: - floating_ip_settings = kwargs.get('floating_ip_settings') - if floating_ip_settings: - for floating_ip_config in floating_ip_settings: - if isinstance(floating_ip_config, FloatingIpSettings): - self.floating_ip_settings.append(floating_ip_config) - else: - self.floating_ip_settings.append(FloatingIpSettings( - **floating_ip_config['floating_ip'])) - - if kwargs.get('vm_boot_timeout'): - self.vm_boot_timeout = kwargs['vm_boot_timeout'] - else: - self.vm_boot_timeout = 900 + derived_inst_creator = OpenStackVmInstance( + os_creds, derived_inst_config, image_config, keypair_config) + derived_inst_creator.initialize() + return derived_inst_creator - if kwargs.get('vm_delete_timeout'): - self.vm_delete_timeout = kwargs['vm_delete_timeout'] - else: - self.vm_delete_timeout = 300 - - if kwargs.get('ssh_connect_timeout'): - self.ssh_connect_timeout = kwargs['ssh_connect_timeout'] - else: - self.ssh_connect_timeout = 180 - if kwargs.get('availability_zone'): - self.availability_zone = kwargs['availability_zone'] - else: - self.availability_zone = None +class VmInstanceSettings(VmInstanceConfig): + """ + Deprecated, use snaps.config.vm_inst.VmInstanceConfig instead + """ + def __init__(self, **kwargs): + from warnings import warn + warn('Use snaps.config.vm_inst.VmInstanceConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) - if not self.name or not self.flavor: - raise Exception( - 'Instance configuration requires the attributes: name, flavor') - if len(self.port_settings) == 0: - raise Exception( - 'Instance configuration requires port settings (aka. NICS)') +class FloatingIpSettings(FloatingIpConfig): + """ + Deprecated, use snaps.config.vm_inst.FloatingIpConfig instead + """ + def __init__(self, **kwargs): + from warnings import warn + warn('Use snaps.config.vm_inst.FloatingIpConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) -class FloatingIpSettings: +class VmInstanceCreationError(Exception): """ - Class responsible for holding configuration settings for a floating IP + Exception to be thrown when an VM instance cannot be created """ - def __init__(self, **kwargs): - """ - Constructor - :param name: the name of the floating IP - :param port_name: the name of the router to the external network - :param router_name: the name of the router to the external network - :param subnet_name: the name of the subnet on which to attach the - floating IP - :param provisioning: when true, this floating IP can be used for - provisioning - - TODO - provisioning flag is a hack as I have only observed a single - Floating IPs that actually works on an instance. Multiple floating IPs - placed on different subnets from the same port are especially - troublesome as you cannot predict which one will actually connect. - For now, it is recommended not to setup multiple floating IPs on an - instance unless absolutely necessary. - """ - self.name = kwargs.get('name') - self.port_name = kwargs.get('port_name') - self.router_name = kwargs.get('router_name') - self.subnet_name = kwargs.get('subnet_name') - if kwargs.get('provisioning') is not None: - self.provisioning = kwargs['provisioning'] - else: - self.provisioning = True - if not self.name or not self.port_name or not self.router_name: - raise Exception( - 'The attributes name, port_name and router_name are required ' - 'for FloatingIPSettings') +class FloatingIPAllocationError(Exception): + """ + Exception to be thrown when an VM instance cannot allocate a floating IP + """