diff options
Diffstat (limited to 'snaps/openstack/create_instance.py')
-rw-r--r-- | snaps/openstack/create_instance.py | 173 |
1 files changed, 83 insertions, 90 deletions
diff --git a/snaps/openstack/create_instance.py b/snaps/openstack/create_instance.py index 336c936..d91e360 100644 --- a/snaps/openstack/create_instance.py +++ b/snaps/openstack/create_instance.py @@ -15,7 +15,6 @@ import logging import time -from neutronclient.common.exceptions import PortNotFoundClient from novaclient.exceptions import NotFound, BadRequest from snaps.config.vm_inst import VmInstanceConfig, FloatingIpConfig @@ -255,19 +254,25 @@ class OpenStackVmInstance(OpenStackComputeObject): # Cleanup 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)) + logger.info('Deleting Floating IP - ' + floating_ip.ip) + neutron_utils.delete_floating_ip(self.__neutron, floating_ip) + 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: + # Cleanup ports + for name, port in self.__ports: + logger.info('Deleting Port with ID - %s ', port.id) + neutron_utils.delete_port(self.__neutron, port) + + self.__ports = list() + + if self.__vm: + # 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: vm = nova_utils.detach_volume( self._nova, self.__neutron, self.__vm, volume, 30) if vm: @@ -275,50 +280,32 @@ class OpenStackVmInstance(OpenStackComputeObject): 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']) + 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 with ID - %s ', port.id) - try: - neutron_utils.delete_port(self.__neutron, port) - except PortNotFoundClient as e: - logger.warning('Unexpected error deleting port - %s', e) - pass - self.__ports = list() + # Cleanup VM + logger.info( + 'Deleting VM instance - ' + self.instance_settings.name) - # Cleanup VM - if self.__vm: try: - logger.info( - 'Deleting VM instance - ' + self.instance_settings.name) nova_utils.delete_vm_instance(self._nova, self.__vm) - except Exception as e: - logger.error('Error deleting VM - %s', e) + except NotFound as e: + logger.warn('Instance already deleted - %s', e) # Block until instance cannot be found or returns the status of # DELETED logger.info('Checking deletion status') - try: - if self.vm_deleted(block=True): - logger.info( - 'VM has been properly deleted VM with name - %s', - self.instance_settings.name) - self.__vm = None - else: - logger.error( - 'VM not deleted within the timeout period of %s ' - 'seconds', self.instance_settings.vm_delete_timeout) - except Exception as e: + if self.vm_deleted(block=True): + logger.info( + 'VM has been properly deleted VM with name - %s', + self.instance_settings.name) + self.__vm = None + else: logger.error( - 'Unexpected error while checking VM instance status - %s', - e) + 'VM not deleted within the timeout period of %s ' + 'seconds', self.instance_settings.vm_delete_timeout) def __query_ports(self, port_settings): """ @@ -489,25 +476,6 @@ class OpenStackVmInstance(OpenStackComputeObject): """ 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: the value returned by ansible_utils.apply_ansible_playbook() - """ - 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) - 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): """ Returns the first floating IP tagged with the Floating IP name if @@ -528,31 +496,6 @@ class OpenStackVmInstance(OpenStackComputeObject): for key, fip in self.__floating_ip_dict.items(): return fip - def __config_nic(self, nic_name, port, ip): - """ - Although ports/NICs can contain multiple IPs, this code currently only - supports the first. - - :param nic_name: Name of the interface - :param port: The port information containing the expected IP values. - :param ip: The IP on which to apply the playbook. - :return: the return value from ansible - """ - port_ip = port.ips[0]['ip_address'] - variables = { - 'floating_ip': ip, - 'nic_name': nic_name, - 'nic_ip': port_ip - } - - if self.image_settings.nic_config_pb_loc and self.keypair_settings: - return self.apply_ansible_playbook( - self.image_settings.nic_config_pb_loc, variables) - else: - logger.warning( - 'VM %s cannot self configure NICs eth1++. No playbook or ' - 'keypairs found.', self.instance_settings.name) - def apply_ansible_playbook(self, pb_file_loc, variables=None, fip_name=None): """ @@ -722,6 +665,56 @@ class OpenStackVmInstance(OpenStackComputeObject): return True return False + def cloud_init_complete(self, block=False, poll_interval=POLL_INTERVAL): + """ + Returns true when the VM's cloud-init routine has completed. + Note: this is currently done via SSH, therefore, if this instance does + not have a Floating IP or a running SSH server, this routine + will always return False or raise an Exception + :param block: When true, thread will block until active or timeout + value in seconds has been exceeded (False) + :param poll_interval: The polling interval + :return: T/F + """ + # sleep and wait for VM status change + logger.info('Checking if cloud-init has completed') + + timeout = self.instance_settings.cloud_init_timeout + + if self.vm_active(block=True) and self.vm_ssh_active(block=True): + if block: + start = time.time() + else: + start = time.time() - timeout + + while timeout > time.time() - start: + status = self.__cloud_init_complete() + if status: + logger.info('cloud-init complete for VM instance') + return True + + logger.debug('Retry cloud-init query in ' + str( + poll_interval) + ' seconds') + time.sleep(poll_interval) + logger.debug('cloud-init complete timeout in ' + str( + timeout - (time.time() - start))) + + logger.error('Timeout waiting for cloud-init to complete') + return False + + def __cloud_init_complete(self): + """ + Returns True when can create a SSH session else False + :return: T/F + """ + if len(self.__floating_ip_dict) > 0: + ssh = self.ssh_client() + if ssh: + stdin1, stdout1, sterr1 = ssh.exec_command( + 'ls -l /var/lib/cloud/instance/boot-finished') + return stdout1.channel.recv_exit_status() == 0 + return False + def get_floating_ip(self, fip_name=None): """ Returns the floating IP object byt name if found, else the first known, |