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) is_uefi_boot_mode = deploy_utils.get_boot_mode_for_deploy(task.node) == "uefi" if is_uefi_boot_mode and not CONF.pxe.ipxe_enabled: 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: # Get xx.xx.xx.xx based grub config file ip_address_path = _get_pxe_ip_address_path(port_ip_address, False) # Get 0AOAOAOA based elilo config file hex_ip_path = _get_pxe_ip_address_path(port_ip_address, True) except exception.InvalidIPv4Address: continue # Cleaning up config files created for grub2. ironic_utils.unlink_without_raise(ip_address_path) # Cleaning up config files created for elilo. ironic_utils.unlink_without_raise(hex_ip_path) else: for port in task.ports: client_id = port.extra.get("client-id") ironic_utils.unlink_without_raise(_get_pxe_mac_path(port.address, client_id=client_id)) utils.rmtree_without_raise(os.path.join(get_root_dir(), task.node.uuid))
def tear_down(self, task, node): """Tear down a previous deployment. Given a node that has been previously deployed to, do all cleanup and tear down necessary to "un-deploy" that node. :param task: a TaskManager instance. :param node: the Node to act upon. :returns: deploy state DELETED. """ #FIXME(ghe): Possible error to get image info if eliminated from glance # Retrieve image info and store in db # If we keep master images, no need to get the info, we may ignore this pxe_info = _get_tftp_image_info(node) d_info = _parse_driver_info(node) for label in pxe_info: (uuid, path) = pxe_info[label] master_path = os.path.join(CONF.pxe.tftp_master_path, uuid) utils.unlink_without_raise(path) _unlink_master_image(master_path) utils.unlink_without_raise(_get_pxe_config_file_path( node['instance_uuid'])) for port in _get_node_mac_addresses(task, node): 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['instance_uuid'])) _destroy_images(d_info) return states.DELETED
def _download_image(self, href, master_path, dest_path, ctx=None, force_raw=True): """Download image by href and store at a given path. This method should be called with uuid-specific lock taken. :param href: image UUID or href to fetch :param master_path: destination master path :param dest_path: destination file path :param ctx: context :param force_raw: boolean value, whether to convert the image to raw format """ # TODO(ghe): timeout and retry for downloads # TODO(ghe): logging when image cannot be created tmp_dir = tempfile.mkdtemp(dir=self.master_dir) tmp_path = os.path.join(tmp_dir, href.split('/')[-1]) try: _fetch(ctx, href, tmp_path, self._image_service, force_raw) # NOTE(dtantsur): no need for global lock here - master_path # will have link count >1 at any moment, so won't be cleaned up os.link(tmp_path, master_path) os.link(master_path, dest_path) finally: utils.rmtree_without_raise(tmp_dir)
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 clean_up(self, task, node): """Clean up the deployment environment for this node. Delete the deploy and user images from the local cache, if no remaining active nodes require them. 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. :param node: the Node to act upon. """ pxe_info = _get_tftp_image_info(node, task.context) d_info = _parse_driver_info(node) for label in pxe_info: (uuid, path) = pxe_info[label] master_path = os.path.join(CONF.pxe.tftp_master_path, uuid) utils.unlink_without_raise(path) _unlink_master_image(master_path) utils.unlink_without_raise(_get_pxe_config_file_path( node.uuid)) 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.rmtree_without_raise( os.path.join(CONF.pxe.tftp_root, node.uuid)) _destroy_images(d_info, node.uuid) _destroy_token_file(node)
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)
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 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 destroy_images(node_uuid): """Delete instance's image file. :param node_uuid: the uuid of the ironic node. """ ironic_utils.unlink_without_raise(_get_image_file_path(node_uuid)) utils.rmtree_without_raise(_get_image_dir_path(node_uuid)) InstanceImageCache().clean_up()
def destroy_images(node_uuid): """Delete instance's image file. :param node_uuid: the uuid of the ironic node. """ il_utils.unlink_without_raise(_get_image_file_path(node_uuid)) utils.rmtree_without_raise(_get_image_dir_path(node_uuid)) InstanceImageCache().clean_up()
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 clean_up_pxe_config(task, ipxe_enabled=False): """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) is_uefi_boot_mode = (boot_mode_utils.get_boot_mode(task.node) == 'uefi') if is_uefi_boot_mode and not ipxe_enabled: 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: # Get xx.xx.xx.xx based grub config file ip_address_path = _get_pxe_ip_address_path(port_ip_address, False) # NOTE(TheJulia): Remove elilo support after the deprecation # period, in the Queens release. # Get 0AOAOAOA based elilo config file hex_ip_path = _get_pxe_ip_address_path(port_ip_address, True) except exception.InvalidIPv4Address: continue except exception.FailedToGetIPAddressOnPort: continue # Cleaning up config files created for grub2. ironic_utils.unlink_without_raise(ip_address_path) # Cleaning up config files created for elilo. ironic_utils.unlink_without_raise(hex_ip_path) for port in task.ports: client_id = port.extra.get('client-id') # syslinux, ipxe, etc. ironic_utils.unlink_without_raise( _get_pxe_mac_path(port.address, client_id=client_id, ipxe_enabled=ipxe_enabled)) # Grub2 MAC address based confiuration ironic_utils.unlink_without_raise( _get_pxe_grub_mac_path(port.address)) if ipxe_enabled: utils.rmtree_without_raise(os.path.join(get_ipxe_root_dir(), task.node.uuid)) else: utils.rmtree_without_raise(os.path.join(get_root_dir(), task.node.uuid))
def cleanup_resources(self): """Cleanup all resources of the list. Must be idempotent. Must return None if called when action resources are not fetched. """ # Cleanup resources for res in self.resources: res.cleanup() # Cleanup resource dirs res_dirs = [] for res in self.resources: res_dirs.extend(res.get_dir_names()) for dir in set(res_dirs): utils.rmtree_without_raise(dir)
def _download_image(self, href, master_path, dest_path, ctx=None, force_raw=True): """Download image by href and store at a given path. This method should be called with uuid-specific lock taken. :param href: image UUID or href to fetch :param master_path: destination master path :param dest_path: destination file path :param ctx: context :param force_raw: boolean value, whether to convert the image to raw format :raise ImageDownloadFailed: when the image cache and the image HTTP or TFTP location are on different file system, causing hard link to fail. """ # TODO(ghe): timeout and retry for downloads # TODO(ghe): logging when image cannot be created tmp_dir = tempfile.mkdtemp(dir=self.master_dir) tmp_path = os.path.join(tmp_dir, href.split('/')[-1]) try: _fetch(ctx, href, tmp_path, force_raw) # NOTE(dtantsur): no need for global lock here - master_path # will have link count >1 at any moment, so won't be cleaned up os.link(tmp_path, master_path) os.link(master_path, dest_path) except OSError as exc: msg = (_("Could not link image %(img_href)s from %(src_path)s " "to %(dst_path)s, error: %(exc)s") % { 'img_href': href, 'src_path': master_path, 'dst_path': dest_path, 'exc': exc }) LOG.error(msg) raise exception.ImageDownloadFailed(msg) finally: utils.rmtree_without_raise(tmp_dir)
def deactivate_bootloader(self, context, node, instance): """Delete PXE bootloader images and config.""" try: db.bm_node_update( context, node['id'], { 'deploy_key': None, 'image_path': None, 'pxe_config_path': None, 'root_mb': 0, 'swap_mb': 0 }) except exception.NodeNotFound: pass # NOTE(danms): the instance_type extra_specs do not need to be # present/correct at deactivate time, so pass something empty # to avoid an extra lookup instance_type = dict( extra_specs={ 'baremetal:deploy_ramdisk_id': 'ignore', 'baremetal:deploy_kernel_id': 'ignore' }) try: image_info = get_tftp_image_info(instance, instance_type) except exception.NovaException: pass else: for label in image_info.keys(): (uuid, path) = image_info[label] utils.unlink_without_raise(path) utils.unlink_without_raise(get_pxe_config_file_path(instance)) try: macs = self._collect_mac_addresses(context, node) except db_exc.DBError: pass else: for mac in macs: utils.unlink_without_raise(get_pxe_mac_path(mac)) utils.rmtree_without_raise( os.path.join(CONF.tftp_root, instance['uuid']))
def _download_image(self, uuid, master_path, dest_path, ctx=None): """Download image from Glance and store at a given path. This method should be called with uuid-specific lock taken. :param uuid: image UUID or href to fetch :param master_path: destination master path :param dest_path: destination file path :param ctx: context """ #TODO(ghe): timeout and retry for downloads #TODO(ghe): logging when image cannot be created tmp_dir = tempfile.mkdtemp(dir=self.master_dir) tmp_path = os.path.join(tmp_dir, uuid) try: _fetch_to_raw(ctx, uuid, tmp_path, self._image_service) # NOTE(dtantsur): no need for global lock here - master_path # will have link count >1 at any moment, so won't be cleaned up os.link(tmp_path, master_path) os.link(master_path, dest_path) finally: utils.rmtree_without_raise(tmp_dir)
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) is_uefi_boot_mode = (deploy_utils.get_boot_mode_for_deploy( task.node) == 'uefi') if is_uefi_boot_mode and not CONF.pxe.ipxe_enabled: 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: # Get xx.xx.xx.xx based grub config file ip_address_path = _get_pxe_ip_address_path( port_ip_address, False) # Get 0AOAOAOA based elilo config file hex_ip_path = _get_pxe_ip_address_path(port_ip_address, True) except exception.InvalidIPv4Address: continue # Cleaning up config files created for grub2. ironic_utils.unlink_without_raise(ip_address_path) # Cleaning up config files created for elilo. ironic_utils.unlink_without_raise(hex_ip_path) else: for mac in driver_utils.get_node_mac_addresses(task): ironic_utils.unlink_without_raise(_get_pxe_mac_path(mac)) # TODO(lucasagomes): Backward compatibility with :hexraw, # to be removed in Mitaka. # see: https://bugs.launchpad.net/ironic/+bug/1441710 if CONF.pxe.ipxe_enabled: ironic_utils.unlink_without_raise( _get_pxe_mac_path(mac, delimiter='')) utils.rmtree_without_raise(os.path.join(get_root_dir(), task.node.uuid))
def deactivate_bootloader(self, context, node, instance): """Delete PXE bootloader images and config.""" try: db.bm_node_update(context, node['id'], {'deploy_key': None, 'image_path': None, 'pxe_config_path': None, 'root_mb': 0, 'swap_mb': 0}) except exception.NodeNotFound: pass # NOTE(danms): the instance_type extra_specs do not need to be # present/correct at deactivate time, so pass something empty # to avoid an extra lookup instance_type = dict(extra_specs={ 'baremetal:deploy_ramdisk_id': 'ignore', 'baremetal:deploy_kernel_id': 'ignore'}) try: image_info = get_tftp_image_info(instance, instance_type) except exception.NovaException: pass else: for label in image_info.keys(): (uuid, path) = image_info[label] utils.unlink_without_raise(path) utils.unlink_without_raise(get_pxe_config_file_path(instance)) try: macs = self._collect_mac_addresses(context, node) except db_exc.DBError: pass else: for mac in macs: utils.unlink_without_raise(get_pxe_mac_path(mac)) utils.rmtree_without_raise( os.path.join(CONF.tftp_root, instance['uuid']))
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) is_uefi_boot_mode = (deploy_utils.get_boot_mode_for_deploy(task.node) == 'uefi') if is_uefi_boot_mode and not CONF.pxe.ipxe_enabled: 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: # Get xx.xx.xx.xx based grub config file ip_address_path = _get_pxe_ip_address_path(port_ip_address, False) # Get 0AOAOAOA based elilo config file hex_ip_path = _get_pxe_ip_address_path(port_ip_address, True) except exception.InvalidIPv4Address: continue # Cleaning up config files created for grub2. ironic_utils.unlink_without_raise(ip_address_path) # Cleaning up config files created for elilo. ironic_utils.unlink_without_raise(hex_ip_path) else: for port in task.ports: client_id = port.extra.get('client-id') ironic_utils.unlink_without_raise( _get_pxe_mac_path(port.address, client_id=client_id)) utils.rmtree_without_raise(os.path.join(get_root_dir(), task.node.uuid))
def deactivate_bootloader(self, context, node, instance): """Delete Tilera bootloader images and config.""" try: db.bm_node_update(context, node['id'], {'deploy_key': None, 'image_path': None, 'pxe_config_path': None, 'root_mb': 0, 'swap_mb': 0}) except exception.NodeNotFound: pass tilera_nfs_path = get_tilera_nfs_path(node['id']) if os.path.ismount(tilera_nfs_path): utils.execute('rpc.mountd', run_as_root=True) utils.execute('umount', '-f', tilera_nfs_path, run_as_root=True) try: image_info = get_tftp_image_info(instance) except exception.NovaException: pass else: for label in image_info.keys(): (uuid, path) = image_info[label] utils.unlink_without_raise(path) try: self._collect_mac_addresses(context, node) except db_exc.DBError: pass if os.path.exists(os.path.join(CONF.tftp_root, instance['uuid'])): utils.rmtree_without_raise( os.path.join(CONF.tftp_root, instance['uuid']))
def _download_image(self, href, master_path, dest_path, ctx=None, force_raw=True): """Download image by href and store at a given path. This method should be called with uuid-specific lock taken. :param href: image UUID or href to fetch :param master_path: destination master path :param dest_path: destination file path :param ctx: context :param force_raw: boolean value, whether to convert the image to raw format :raise ImageDownloadFailed: when the image cache and the image HTTP or TFTP location are on different file system, causing hard link to fail. """ # TODO(ghe): timeout and retry for downloads # TODO(ghe): logging when image cannot be created tmp_dir = tempfile.mkdtemp(dir=self.master_dir) tmp_path = os.path.join(tmp_dir, href.split('/')[-1]) try: _fetch(ctx, href, tmp_path, force_raw) # NOTE(dtantsur): no need for global lock here - master_path # will have link count >1 at any moment, so won't be cleaned up os.link(tmp_path, master_path) os.link(master_path, dest_path) except OSError as exc: msg = (_("Could not link image %(img_href)s from %(src_path)s " "to %(dst_path)s, error: %(exc)s") % {'img_href': href, 'src_path': master_path, 'dst_path': dest_path, 'exc': exc}) LOG.error(msg) raise exception.ImageDownloadFailed(msg) finally: utils.rmtree_without_raise(tmp_dir)
def config_temp_dir(self, option, group=None): """Override a config option with a temporary directory.""" temp_dir = tempfile.mkdtemp() self.addCleanup(lambda: common_utils.rmtree_without_raise(temp_dir)) self.config(**{option: temp_dir, 'group': group})
def clean_up_instance(self, task): node = task.node # TODO(jroll) okay to not raise an exception here? utils.rmtree_without_raise(_insecure_http_root(node.uuid)) utils.rmtree_without_raise(_secure_http_root(node.uuid))
def destroy_images(self, context, node, instance): """Delete instance's image file.""" utils.unlink_without_raise(get_image_file_path(instance)) utils.rmtree_without_raise(get_image_dir_path(instance))
def _destroy_images(d_info, node_uuid): """Delete instance's image file.""" utils.unlink_without_raise(_get_image_file_path(node_uuid)) utils.rmtree_without_raise(_get_image_dir_path(node_uuid)) InstanceImageCache().clean_up()
def _clean_up_resource_dirs(self, task): utils.rmtree_without_raise( resources.get_abs_node_workdir_path(task.node)) utils.rmtree_without_raise( rsync.get_abs_node_workdir_path(task.node))