예제 #1
0
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))
예제 #2
0
파일: pxe.py 프로젝트: nkaul/ironic
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)
예제 #3
0
    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)
예제 #4
0
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))
예제 #5
0
    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)
예제 #6
0
    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()
예제 #7
0
    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()
예제 #8
0
파일: deploy.py 프로젝트: jriguera/ironic
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)
예제 #9
0
 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)
예제 #10
0
    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()
예제 #11
0
파일: pxe.py 프로젝트: stendulker/ironic
    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)
예제 #12
0
    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()
예제 #13
0
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)
예제 #14
0
파일: pxe.py 프로젝트: varunarya10/ironic
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)
예제 #15
0
    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)
예제 #16
0
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))
예제 #17
0
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)
예제 #18
0
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
예제 #19
0
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)
예제 #20
0
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)
예제 #21
0
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)
예제 #22
0
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()
예제 #23
0
파일: pxe.py 프로젝트: nkaul/ironic
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)
예제 #24
0
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()
예제 #25
0
파일: boot.py 프로젝트: juliakreger/ironic
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)
예제 #26
0
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)
예제 #27
0
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)
예제 #28
0
파일: common.py 프로젝트: jriguera/ironic
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)
예제 #29
0
    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)
예제 #30
0
파일: common.py 프로젝트: yhvh/ironic
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)
예제 #31
0
파일: ipmitool.py 프로젝트: jumpojoy/ironic
    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))
예제 #32
0
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)
예제 #33
0
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)
예제 #34
0
파일: pxe.py 프로젝트: schatt/ironic
    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)
예제 #35
0
    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)
예제 #36
0
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)
예제 #37
0
파일: pxe.py 프로젝트: ader1990/ironic
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)
예제 #38
0
파일: ipmitool.py 프로젝트: yzping/ironic
    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"]))
예제 #39
0
파일: pxe.py 프로젝트: varunarya10/ironic
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)
예제 #40
0
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))
예제 #41
0
파일: pxe.py 프로젝트: nkaul/ironic
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)
예제 #42
0
파일: pxe.py 프로젝트: AsylumCorp/ironic
    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)
예제 #43
0
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))
예제 #44
0
파일: ipmitool.py 프로젝트: skw0rm/ironic
    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']))
예제 #45
0
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))
예제 #46
0
    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
예제 #47
0
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))
예제 #48
0
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)
예제 #49
0
    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
예제 #50
0
    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)
예제 #51
0
파일: pxe.py 프로젝트: nkaul/ironic
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)
예제 #52
0
    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)
예제 #53
0
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))
예제 #54
0
파일: pxe.py 프로젝트: jriguera/ironic
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()
예제 #55
0
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)
예제 #56
0
    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)
예제 #57
0
파일: ipmitool.py 프로젝트: skw0rm/ironic
    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)
예제 #58
0
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))
예제 #59
0
    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)