def clean_up_pxe_config(task): """Clean up the TFTP environment for the task's node. :param task: A TaskManager instance. """ LOG.debug("Cleaning up PXE config for node %s", task.node.uuid) if driver_utils.get_node_capability(task.node, 'boot_mode') == 'uefi': api = dhcp_factory.DHCPFactory().provider ip_addresses = api.get_ip_addresses(task) if not ip_addresses: return for port_ip_address in ip_addresses: try: ip_address_path = _get_pxe_ip_address_path(port_ip_address) except exception.InvalidIPv4Address: continue utils.unlink_without_raise(ip_address_path) else: for mac in driver_utils.get_node_mac_addresses(task): utils.unlink_without_raise(_get_pxe_mac_path(mac)) utils.rmtree_without_raise(os.path.join(get_root_dir(), task.node.uuid))
def _destroy_images(d_info, node_uuid): """Delete instance's image file.""" image_uuid = service_utils.parse_image_ref(d_info['image_source'])[0] utils.unlink_without_raise(_get_image_file_path(node_uuid)) utils.rmtree_without_raise(_get_image_dir_path(node_uuid)) master_image = os.path.join(CONF.pxe.instance_master_path, image_uuid) _unlink_master_image(master_image)
def start_console(self, task): """Start a remote console for the node. :param task: a TaskManager instance containing the node to act on. :raises: MissingParameterValue when required ipmi credentials are missing. :raises: InvalidParameterValue when the IPMI terminal port is not an integer. :raises: ConsoleError if unable to start the console process. """ driver_info = _parse_driver_info(task.node) path = _console_pwfile_path(driver_info['uuid']) pw_file = console_utils.make_persistent_password_file( path, driver_info['password']) console_cmd = ("/:%(uid)s:%(gid)s:HOME:pyghmicons %(bmc)s" " %(user)s" " %(passwd_file)s" % {'uid': os.getuid(), 'gid': os.getgid(), 'bmc': driver_info['address'], 'user': driver_info['username'], 'passwd_file': pw_file}) try: console_utils.start_shellinabox_console(driver_info['uuid'], driver_info['port'], console_cmd) except exception.ConsoleError: with excutils.save_and_reraise_exception(): utils.unlink_without_raise(path)
def test_unlink(self): self.mox.StubOutWithMock(os, "unlink") os.unlink("/fake/path") self.mox.ReplayAll() utils.unlink_without_raise("/fake/path") self.mox.VerifyAll()
def test_unlink_ENOENT(self): self.mox.StubOutWithMock(os, "unlink") os.unlink("/fake/path").AndRaise(OSError(errno.ENOENT)) self.mox.ReplayAll() utils.unlink_without_raise("/fake/path") self.mox.VerifyAll()
def _clean_up_boot_iso_for_instance(node): """Deletes the boot ISO if it was created for the instance. :param node: an ironic node object. """ ilo_boot_iso = node.instance_info.get('ilo_boot_iso') if not ilo_boot_iso: return if ilo_boot_iso.startswith('swift'): swift_api = swift.SwiftAPI() container = CONF.ilo.swift_ilo_container boot_iso_object_name = _get_boot_iso_object_name(node) try: swift_api.delete_object(container, boot_iso_object_name) except exception.SwiftOperationError as e: LOG.exception( _LE("Failed to clean up boot ISO for node " "%(node)s. Error: %(error)s."), { 'node': node.uuid, 'error': e }) elif CONF.ilo.use_web_server_for_images: result = urlparse.urlparse(ilo_boot_iso) ilo_boot_iso_name = os.path.basename(result.path) boot_iso_path = os.path.join(CONF.deploy.http_root, ilo_boot_iso_name) utils.unlink_without_raise(boot_iso_path)
def cleanup(self): if not self.is_fetched(): return bareon_utils.umount_without_raise(self.mount_point, '-fl') self._raw.pop('mount_point', None) utils.unlink_without_raise(self.local_path) self._raw.pop('local_path', None)
def clean_up(self, task): """Clean up the deployment environment for the task's node. Unlinks TFTP and instance images and triggers image cache cleanup. Removes the TFTP configuration files for this node. :param task: a TaskManager instance containing the node to act on. """ node = task.node try: pxe_info = _get_image_info(node, task.context) except exception.MissingParameterValue as e: LOG.warning(_LW('Could not get image info to clean up images ' 'for node %(node)s: %(err)s'), {'node': node.uuid, 'err': e}) else: for label in pxe_info: path = pxe_info[label][1] utils.unlink_without_raise(path) TFTPImageCache().clean_up() pxe_utils.clean_up_pxe_config(task) iscsi_deploy.destroy_images(node.uuid)
def _link_ip_address_pxe_configs(task, hex_form): """Link each IP address with the PXE configuration file. :param task: A TaskManager instance. :param hex_form: Boolean value indicating if the conf file name should be hexadecimal equivalent of supplied ipv4 address. :raises: FailedToGetIPAddressOnPort :raises: InvalidIPv4Address """ pxe_config_file_path = get_pxe_config_file_path(task.node.uuid) api = dhcp_factory.DHCPFactory().provider ip_addrs = api.get_ip_addresses(task) if not ip_addrs: raise exception.FailedToGetIPAddressOnPort(_( "Failed to get IP address for any port on node %s.") % task.node.uuid) for port_ip_address in ip_addrs: ip_address_path = _get_pxe_ip_address_path(port_ip_address, hex_form) utils.unlink_without_raise(ip_address_path) relative_source_path = os.path.relpath( pxe_config_file_path, os.path.dirname(ip_address_path)) utils.create_link_without_raise(relative_source_path, ip_address_path)
def clean_up(self, task): """Clean up the deployment environment for the task's node. Unlinks TFTP and instance images and triggers image cache cleanup. Removes the TFTP configuration files for this node. As a precaution, this method also ensures the keystone auth token file was removed. :param task: a TaskManager instance containing the node to act on. """ node = task.node try: pxe_info = _get_image_info(node, task.context) except exception.MissingParameterValue as e: LOG.warning( _LW('Could not get image info to clean up images ' 'for node %(node)s: %(err)s'), { 'node': node.uuid, 'err': e }) else: for label in pxe_info: path = pxe_info[label][1] utils.unlink_without_raise(path) TFTPImageCache().clean_up() pxe_utils.clean_up_pxe_config(task) iscsi_deploy.destroy_images(node.uuid) _destroy_token_file(node)
def _stop_console(node_uuid): """Close the serial console for a node Kills the console process and deletes the PID file. :param node_uuid: the UUID of the node :raises: NoConsolePid if no console PID was found :raises: ConsoleError if unable to stop the console process """ try: console_pid = _get_console_pid(node_uuid) os.kill(console_pid, signal.SIGTERM) except OSError as exc: if exc.errno != errno.ESRCH: msg = (_("Could not stop the console for node '%(node)s'. " "Reason: %(err)s.") % {'node': node_uuid, 'err': exc}) raise exception.ConsoleError(message=msg) else: LOG.warning(_LW("Console process for node %s is not running " "but pid file exists while trying to stop " "shellinabox console."), node_uuid) finally: utils.unlink_without_raise(_get_console_pid_file(node_uuid))
def _remove_share_file(share_filename): """remove a file in the share file system. :param share_filename: a file name to be removed. """ share_fullpathname = os.path.join( CONF.irmc.remote_image_share_name, share_filename) utils.unlink_without_raise(share_fullpathname)
def url_download_raw(context, node, url): if not url: return resource_path = url_download(context, node, url) with open(resource_path) as f: raw = f.read() utils.unlink_without_raise(resource_path) return raw
def _clean_up_pxe(task): """Clean up left over PXE and DHCP files.""" pxe_info = _get_tftp_image_info(task.node) for label in pxe_info: path = pxe_info[label][1] utils.unlink_without_raise(path) AgentTFTPImageCache().clean_up() pxe_utils.clean_up_pxe_config(task)
def _create_token_file(task): """Save PKI token to file.""" token_file_path = _get_token_file_path(task.node.uuid) token = task.context.auth_token if token: utils.write_to_file(token_file_path, token) else: utils.unlink_without_raise(token_file_path)
def destroy_images(node_uuid): """Delete instance's image file. :param node_uuid: the uuid of the ironic node. """ utils.unlink_without_raise(_get_image_file_path(node_uuid)) utils.rmtree_without_raise(_get_image_dir_path(node_uuid)) InstanceImageCache().clean_up()
def _create_token_file(task, node): """Save PKI token to file.""" token_file_path = _get_token_file_path(node['uuid']) token = task.context.auth_token if token: utils.write_to_file(token_file_path, token) else: utils.unlink_without_raise(token_file_path)
def _remove_share_file(share_filename): """Remove given file from the share file system. :param share_filename: a file name to be removed. """ share_fullpathname = os.path.join( CONF.irmc.remote_image_share_name, share_filename) utils.unlink_without_raise(share_fullpathname)
def _get_configdrive(configdrive, node_uuid): """Get the information about size and location of the configdrive. :param configdrive: Base64 encoded Gzipped configdrive content or configdrive HTTP URL. :param node_uuid: Node's uuid. Used for logging. :raises: InstanceDeployFailure if it can't download or decode the config drive. :returns: A tuple with the size in MiB and path to the uncompressed configdrive file. """ # Check if the configdrive option is a HTTP URL or the content directly is_url = utils.is_http_url(configdrive) if is_url: try: data = requests.get(configdrive).content except requests.exceptions.RequestException as e: raise exception.InstanceDeployFailure( _("Can't download the configdrive content for node %(node)s " "from '%(url)s'. Reason: %(reason)s") % {'node': node_uuid, 'url': configdrive, 'reason': e}) else: data = configdrive try: data = six.BytesIO(base64.b64decode(data)) except TypeError: error_msg = (_('Config drive for node %s is not base64 encoded ' 'or the content is malformed.') % node_uuid) if is_url: error_msg += _(' Downloaded from "%s".') % configdrive raise exception.InstanceDeployFailure(error_msg) configdrive_file = tempfile.NamedTemporaryFile(delete=False, prefix='configdrive', dir=CONF.tempdir) configdrive_mb = 0 with gzip.GzipFile('configdrive', 'rb', fileobj=data) as gunzipped: try: shutil.copyfileobj(gunzipped, configdrive_file) except EnvironmentError as e: # Delete the created file utils.unlink_without_raise(configdrive_file.name) raise exception.InstanceDeployFailure( _('Encountered error while decompressing and writing ' 'config drive for node %(node)s. Error: %(exc)s') % {'node': node_uuid, 'exc': e}) else: # Get the file size and convert to MiB configdrive_file.seek(0, os.SEEK_END) bytes_ = configdrive_file.tell() configdrive_mb = int(math.ceil(float(bytes_) / units.Mi)) finally: configdrive_file.close() return (configdrive_mb, configdrive_file.name)
def _get_configdrive(configdrive, node_uuid): """Get the information about size and location of the configdrive. :param configdrive: Base64 encoded Gzipped configdrive content or configdrive HTTP URL. :param node_uuid: Node's uuid. Used for logging. :raises: InstanceDeployFailure if it can't download or decode the config drive. :returns: A tuple with the size in MiB and path to the uncompressed configdrive file. """ # Check if the configdrive option is a HTTP URL or the content directly is_url = utils.is_http_url(configdrive) if is_url: try: data = requests.get(configdrive).content except requests.exceptions.RequestException as e: raise exception.InstanceDeployFailure( _("Can't download the configdrive content for node %(node)s " "from '%(url)s'. Reason: %(reason)s") % {'node': node_uuid, 'url': configdrive, 'reason': e}) else: data = configdrive try: data = six.StringIO(base64.b64decode(data)) except TypeError: error_msg = (_('Config drive for node %s is not base64 encoded ' 'or the content is malformed.') % node_uuid) if is_url: error_msg += _(' Downloaded from "%s".') % configdrive raise exception.InstanceDeployFailure(error_msg) configdrive_file = tempfile.NamedTemporaryFile(delete=False, prefix='configdrive') configdrive_mb = 0 with gzip.GzipFile('configdrive', 'rb', fileobj=data) as gunzipped: try: shutil.copyfileobj(gunzipped, configdrive_file) except EnvironmentError as e: # Delete the created file utils.unlink_without_raise(configdrive_file.name) raise exception.InstanceDeployFailure( _('Encountered error while decompressing and writing ' 'config drive for node %(node)s. Error: %(exc)s') % {'node': node_uuid, 'exc': e}) else: # Get the file size and convert to MiB configdrive_file.seek(0, os.SEEK_END) bytes_ = configdrive_file.tell() configdrive_mb = int(math.ceil(float(bytes_) / units.Mi)) finally: configdrive_file.close() return (configdrive_mb, configdrive_file.name)
def destroy_floppy_image_from_web_server(node): """Removes the temporary floppy image. It removes the floppy image created for deploy. :param node: an ironic node object. """ object_name = _get_floppy_image_name(node) image_path = os.path.join(CONF.deploy.http_root, object_name) utils.unlink_without_raise(image_path)
def cleanup(self): """Cleanup files used to store the resource locally. Must be idempotent. Must return None if called when resources is not fetched. """ if not self.is_fetched(): return utils.unlink_without_raise(self.local_path) self._raw.pop('local_path', None)
def stop_console(self, task): """Stop the remote console session for the node. :param task: a task from TaskManager :raises: ConsoleError if unable to stop the console """ try: console_utils.stop_shellinabox_console(task.node.uuid) finally: utils.unlink_without_raise( _console_pwfile_path(task.node.uuid))
def _link_mac_pxe_configs(task): """Link each MAC address with the PXE configuration file. :param task: A TaskManager instance. """ pxe_config_file_path = get_pxe_config_file_path(task.node.uuid) for mac in driver_utils.get_node_mac_addresses(task): mac_path = _get_pxe_mac_path(mac) utils.unlink_without_raise(mac_path) utils.create_link_without_raise(pxe_config_file_path, mac_path)
def _create_token_file(task): """Save PKI token to file.""" token_file_path = _get_token_file_path(task.node.uuid) token = task.context.auth_token if token: timeout = CONF.conductor.deploy_callback_timeout if timeout and keystone.token_expires_soon(token, timeout): token = keystone.get_admin_auth_token() utils.write_to_file(token_file_path, token) else: utils.unlink_without_raise(token_file_path)
def activate_bootloader(self, context, node, instance): """Configure PXE boot loader for an instance Kernel and ramdisk images are downloaded by cache_tftp_images, and stored in /tftpboot/{uuid}/ This method writes the instances config file, and then creates symlinks for each MAC address in the instance. By default, the complete layout looks like this: /tftpboot/ ./{uuid}/ kernel ramdisk deploy_kernel deploy_ramdisk config ./pxelinux.cfg/ {mac} -> ../{uuid}/config """ instance_type = self.virtapi.instance_type_get( context, instance['instance_type_id']) image_info = get_tftp_image_info(instance, instance_type) (root_mb, swap_mb) = get_partition_sizes(instance) pxe_config_file_path = get_pxe_config_file_path(instance) image_file_path = get_image_file_path(instance) deployment_key = utils.random_alnum(32) deployment_iscsi_iqn = "iqn-%s" % instance['uuid'] db.bm_node_update( context, node['id'], { 'deploy_key': deployment_key, 'image_path': image_file_path, 'pxe_config_path': pxe_config_file_path, 'root_mb': root_mb, 'swap_mb': swap_mb }) pxe_config = build_pxe_config( node['id'], deployment_key, deployment_iscsi_iqn, image_info['deploy_kernel'][1], image_info['deploy_ramdisk'][1], image_info['kernel'][1], image_info['ramdisk'][1], ) utils.write_to_file(pxe_config_file_path, pxe_config) macs = self._collect_mac_addresses(context, node) for mac in macs: mac_path = get_pxe_mac_path(mac) utils.unlink_without_raise(mac_path) utils.create_link_without_raise(pxe_config_file_path, mac_path)
def stop_console(self, task): """Stop the remote console session for the node. :param task: a TaskManager instance containing the node to act on. :raises: ConsoleError if unable to stop the console process. """ try: console_utils.stop_shellinabox_console(task.node.uuid) finally: password_file = _console_pwfile_path(task.node.uuid) utils.unlink_without_raise(password_file)
def stop_console(self, task): """Stop the remote console session for the node. :param task: a task from TaskManager :raises: InvalidParameterValue if required ipmi parameters are missing :raises: ConsoleError if unable to stop the console """ driver_info = _parse_driver_info(task.node) try: console_utils.stop_shellinabox_console(driver_info["uuid"]) finally: utils.unlink_without_raise(_console_pwfile_path(driver_info["uuid"]))
def _unlink_master_image(path): #TODO(ghe): keep images for a while (kind of local cache) # If an image has been used, it-s likely to be used again # With no space problems, we can keep it, so next time # only a new link needs to be created. # Replace algorithm to look: disk space (trigger) # lru, aged... # os.statvfs # heapq.nlargest(1, [(f, os.stat('./' + f).st_ctime) for f in # os.listdir('.') if os.stat('./' + f).st_nlink == 1], key=lambda s: s[1]) if os.path.exists(path) and os.stat(path).st_nlink == 1: utils.unlink_without_raise(path)
def stop_shellinabox_console(node_uuid): """Close the serial console for a node.""" try: console_pid = _get_console_pid(node_uuid) except exception.NoConsolePid: LOG.warning(_("No console pid found for node %s" " while trying to stop shellinabox console.") % node_uuid) else: # Allow exitcode 99 (RC_UNAUTHORIZED) utils.execute("kill", str(console_pid), check_exit_code=[0, 99]) finally: utils.unlink_without_raise(_get_console_pid_file(node_uuid))
def activate_bootloader(self, context, node, instance): """Configure PXE boot loader for an instance Kernel and ramdisk images are downloaded by cache_tftp_images, and stored in /tftpboot/{uuid}/ This method writes the instances config file, and then creates symlinks for each MAC address in the instance. By default, the complete layout looks like this: /tftpboot/ ./{uuid}/ kernel ramdisk deploy_kernel deploy_ramdisk config ./pxelinux.cfg/ {mac} -> ../{uuid}/config """ instance_type = self.virtapi.instance_type_get( context, instance['instance_type_id']) image_info = get_tftp_image_info(instance, instance_type) (root_mb, swap_mb) = get_partition_sizes(instance) pxe_config_file_path = get_pxe_config_file_path(instance) image_file_path = get_image_file_path(instance) deployment_key = utils.random_alnum(32) deployment_iscsi_iqn = "iqn-%s" % instance['uuid'] db.bm_node_update(context, node['id'], {'deploy_key': deployment_key, 'image_path': image_file_path, 'pxe_config_path': pxe_config_file_path, 'root_mb': root_mb, 'swap_mb': swap_mb}) pxe_config = build_pxe_config( node['id'], deployment_key, deployment_iscsi_iqn, image_info['deploy_kernel'][1], image_info['deploy_ramdisk'][1], image_info['kernel'][1], image_info['ramdisk'][1], ) utils.write_to_file(pxe_config_file_path, pxe_config) macs = self._collect_mac_addresses(context, node) for mac in macs: mac_path = get_pxe_mac_path(mac) utils.unlink_without_raise(mac_path) utils.create_link_without_raise(pxe_config_file_path, mac_path)
def clean_up_pxe_config(task): """Clean up the TFTP environment for the task's node. :param task: A TaskManager instance. """ LOG.debug("Cleaning up PXE config for node %s", task.node.uuid) for mac in driver_utils.get_node_mac_addresses(task): utils.unlink_without_raise(_get_pxe_mac_path(mac)) utils.rmtree_without_raise(os.path.join(CONF.pxe.tftp_root, task.node.uuid))
def stop_console(self, task): """Stop the remote console session for the node. :param task: a task from TaskManager :raises: InvalidParameterValue if required ipmi parameters are missing :raises: ConsoleError if unable to stop the console """ driver_info = _parse_driver_info(task.node) try: console_utils.stop_shellinabox_console(driver_info['uuid']) finally: utils.unlink_without_raise( _console_pwfile_path(driver_info['uuid']))
def _clean_up_too_old(self, listing): """Clean up stage 1: drop images that are older than TTL. :param listing: list of tuples (file name, last used time) :returns: list of files left after clean up """ threshold = time.time() - self._cache_ttl survived = [] for file_name, last_used, stat in listing: if last_used < threshold: utils.unlink_without_raise(file_name) else: survived.append((file_name, last_used, stat)) return survived
def stop_shellinabox_console(node_uuid): """Close the serial console for a node.""" try: console_pid = _get_console_pid(node_uuid) except exception.NoConsolePid: LOG.warning( _("No console pid found for node %s" " while trying to stop shellinabox console.") % node_uuid) else: # Allow exitcode 99 (RC_UNAUTHORIZED) utils.execute('kill', str(console_pid), check_exit_code=[0, 99]) finally: utils.unlink_without_raise(_get_console_pid_file(node_uuid))
def _create_pxe_config(task, pxe_info): """Generate pxe configuration file and link mac ports to it for tftp booting. """ fileutils.ensure_tree(os.path.join(CONF.pxe.tftp_root, task.node.uuid)) fileutils.ensure_tree(os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg')) pxe_config_file_path = _get_pxe_config_file_path(task.node.uuid) pxe_config = _build_pxe_config(task.node, pxe_info, task.context) utils.write_to_file(pxe_config_file_path, pxe_config) for port in driver_utils.get_node_mac_addresses(task): mac_path = _get_pxe_mac_path(port) utils.unlink_without_raise(mac_path) utils.create_link_without_raise(pxe_config_file_path, mac_path)
def stop_console(self, task): """Stop the remote console session for the node. :param task: a TaskManager instance containing the node to act on. :raises: MissingParameterValue when required IPMI credentials or the IPMI terminal port are missing :raises: InvalidParameterValue when the IPMI terminal port is not an integer. :raises: ConsoleError if unable to stop the console process. """ driver_info = _parse_driver_info(task.node) try: console_utils.stop_shellinabox_console(driver_info['uuid']) finally: password_file = _console_pwfile_path(driver_info['uuid']) utils.unlink_without_raise(password_file)
def _create_pxe_config(task, node, pxe_info): """Generate pxe configuration file and link mac ports to it for tftp booting. """ fileutils.ensure_tree(os.path.join(CONF.pxe.tftp_root, node.uuid)) fileutils.ensure_tree(os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg')) pxe_config_file_path = _get_pxe_config_file_path(node.uuid) pxe_config = _build_pxe_config(node, pxe_info, task.context) utils.write_to_file(pxe_config_file_path, pxe_config) for port in driver_utils.get_node_mac_addresses(task, node): mac_path = _get_pxe_mac_path(port) utils.unlink_without_raise(mac_path) utils.create_link_without_raise(pxe_config_file_path, mac_path)
def _stop_console(node_uuid): """Close the serial console for a node Kills the console process and deletes the PID file. :param node_uuid: the UUID of the node :raises: NoConsolePid if no console PID was found :raises: processutils.ProcessExecutionError if unable to stop the process """ try: console_pid = _get_console_pid(node_uuid) # Allow exitcode 99 (RC_UNAUTHORIZED) utils.execute('kill', str(console_pid), check_exit_code=[0, 99]) finally: utils.unlink_without_raise(_get_console_pid_file(node_uuid))
def _clean_up_pxe_env(task, images_info): """Cleanup PXE environment of all the images in images_info. Cleans up the PXE environment for the mentioned images in images_info. :param task: a TaskManager object :param images_info: A dictionary of images whose keys are the image names to be cleaned up (kernel, ramdisk, etc) and values are a tuple of identifier and absolute path. """ for label in images_info: path = images_info[label][1] utils.unlink_without_raise(path) pxe_utils.clean_up_pxe_config(task) TFTPImageCache().clean_up()
def _link_ip_address_pxe_configs(task): """Link each IP address with the PXE configuration file. :param task: A TaskManager instance. :raises: FailedToGetIPAddressOnPort :raises: InvalidIPv4Address """ pxe_config_file_path = get_pxe_config_file_path(task.node.uuid) api = dhcp_factory.DHCPFactory().provider ip_addrs = api.get_ip_addresses(task) if not ip_addrs: raise exception.FailedToGetIPAddressOnPort( _("Failed to get IP address for any port on node %s.") % task.node.uuid) for port_ip_address in ip_addrs: ip_address_path = _get_pxe_ip_address_path(port_ip_address) utils.unlink_without_raise(ip_address_path) utils.create_link_without_raise(pxe_config_file_path, ip_address_path)
def clean_up(self, task): """Clean up the deployment environment for the task's node. Unlinks TFTP and instance images and triggers image cache cleanup. Removes the TFTP configuration files for this node. As a precaution, this method also ensures the keystone auth token file was removed. :param task: a TaskManager instance containing the node to act on. """ node = task.node pxe_info = _get_tftp_image_info(node, task.context) d_info = _parse_deploy_info(node) for label in pxe_info: path = pxe_info[label][1] utils.unlink_without_raise(path) TFTPImageCache().clean_up() pxe_utils.clean_up_pxe_config(task) _destroy_images(d_info, node.uuid) _destroy_token_file(node)
def start_console(self, task): """Start a remote console for the node. :param task: a task from TaskManager :raises: InvalidParameterValue if required ipmi parameters are missing :raises: PasswordFileFailedToCreate if unable to create a file containing the password :raises: ConsoleError if the directory for the PID file cannot be created :raises: ConsoleSubprocessFailed when invoking the subprocess failed """ driver_info = _parse_driver_info(task.node) path = _console_pwfile_path(driver_info['uuid']) pw_file = console_utils.make_persistent_password_file( path, driver_info['password']) ipmi_cmd = ("/:%(uid)s:%(gid)s:HOME:ipmitool -H %(address)s" " -I lanplus -U %(user)s -f %(pwfile)s" % {'uid': os.getuid(), 'gid': os.getgid(), 'address': driver_info['address'], 'user': driver_info['username'], 'pwfile': pw_file}) for name, option in BRIDGING_OPTIONS: if driver_info[name] is not None: ipmi_cmd = " ".join([ipmi_cmd, option, driver_info[name]]) if CONF.debug: ipmi_cmd += " -v" ipmi_cmd += " sol activate" try: console_utils.start_shellinabox_console(driver_info['uuid'], driver_info['port'], ipmi_cmd) except (exception.ConsoleError, exception.ConsoleSubprocessFailed): with excutils.save_and_reraise_exception(): utils.unlink_without_raise(path)
def clean_up_pxe_config(task): """Clean up the TFTP environment for the task's node. :param task: A TaskManager instance. """ LOG.debug("Cleaning up PXE config for node %s", task.node.uuid) if deploy_utils.get_boot_mode_for_deploy(task.node) == 'uefi': api = dhcp_factory.DHCPFactory().provider ip_addresses = api.get_ip_addresses(task) if not ip_addresses: return for port_ip_address in ip_addresses: try: ip_address_path = _get_pxe_ip_address_path(port_ip_address) except exception.InvalidIPv4Address: continue utils.unlink_without_raise(ip_address_path) else: for mac in driver_utils.get_node_mac_addresses(task): utils.unlink_without_raise(_get_pxe_mac_path(mac)) # TODO(lucasagomes): Backward compatibility with :hexraw, # to be removed in M. # see: https://bugs.launchpad.net/ironic/+bug/1441710 if CONF.pxe.ipxe_enabled: utils.unlink_without_raise(_get_pxe_mac_path(mac, delimiter='')) utils.rmtree_without_raise(os.path.join(get_root_dir(), task.node.uuid))
def clean_up(self, task): """Clean up the deployment environment for the task's node. Unlinks TFTP and instance images and triggers image cache cleanup. Removes the TFTP configuration files for this node. As a precaution, this method also ensures the keystone auth token file was removed. :param task: a TaskManager instance containing the node to act on. """ node = task.node pxe_info = _get_tftp_image_info(node, task.context) d_info = _parse_driver_info(node) for label in pxe_info: path = pxe_info[label][1] utils.unlink_without_raise(path) TFTPImageCache().clean_up() utils.unlink_without_raise(_get_pxe_config_file_path(node.uuid)) for port in driver_utils.get_node_mac_addresses(task): mac_path = _get_pxe_mac_path(port) utils.unlink_without_raise(mac_path) utils.rmtree_without_raise(os.path.join(CONF.pxe.tftp_root, node.uuid)) _destroy_images(d_info, node.uuid) _destroy_token_file(node)