Beispiel #1
0
def _link_ip_address_pxe_configs(task, ipxe_enabled=False):
    """Link each IP address with the PXE configuration file.

    :param task: A TaskManager instance.
    :param ipxe_enabled: Default false boolean to indicate if ipxe
                         is in use by the caller.
    :raises: FailedToGetIPAddressOnPort
    :raises: InvalidIPv4Address

    """
    pxe_config_file_path = get_pxe_config_file_path(task.node.uuid,
                                                    ipxe_enabled=ipxe_enabled)

    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)
        ironic_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)
Beispiel #2
0
    def test_create_link(self):
        self.mox.StubOutWithMock(os, "symlink")
        os.symlink("/fake/source", "/fake/link")

        self.mox.ReplayAll()
        utils.create_link_without_raise("/fake/source", "/fake/link")
        self.mox.VerifyAll()
Beispiel #3
0
    def test_create_link(self):
        self.mox.StubOutWithMock(os, "symlink")
        os.symlink("/fake/source", "/fake/link")

        self.mox.ReplayAll()
        utils.create_link_without_raise("/fake/source", "/fake/link")
        self.mox.VerifyAll()
Beispiel #4
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)
        ironic_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)
Beispiel #5
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)
        ironic_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)
Beispiel #6
0
def _link_ip_address_pxe_configs(task, ipxe_enabled=False):
    """Link each IP address with the PXE configuration file.

    :param task: A TaskManager instance.
    :param ipxe_enabled: Default false boolean to indicate if ipxe
                         is in use by the caller.
    :raises: FailedToGetIPAddressOnPort
    :raises: InvalidIPv4Address

    """
    pxe_config_file_path = get_pxe_config_file_path(task.node.uuid,
                                                    ipxe_enabled=ipxe_enabled)

    api = dhcp_factory.DHCPFactory().provider
    ip_addrs = api.get_ip_addresses(task)
    if not ip_addrs:

        if ip_addrs == []:
            LOG.warning("No IP addresses assigned for node %(node)s.",
                        {'node': task.node.uuid})
        else:
            LOG.warning(
                "DHCP address management is not available for node "
                "%(node)s. Operators without Neutron can ignore this "
                "warning.", {'node': task.node.uuid})
        # Just in case, reset to empty list if we got nothing.
        ip_addrs = []
    for port_ip_address in ip_addrs:
        ip_address_path = _get_pxe_ip_address_path(port_ip_address)
        ironic_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)
Beispiel #7
0
    def test_create_link_EEXIST(self):
        self.mox.StubOutWithMock(os, "symlink")
        os.symlink("/fake/source", "/fake/link").AndRaise(
                OSError(errno.EEXIST))

        self.mox.ReplayAll()
        utils.create_link_without_raise("/fake/source", "/fake/link")
        self.mox.VerifyAll()
Beispiel #8
0
    def test_create_link_EEXIST(self):
        self.mox.StubOutWithMock(os, "symlink")
        os.symlink("/fake/source", "/fake/link").AndRaise(
                OSError(errno.EEXIST))

        self.mox.ReplayAll()
        utils.create_link_without_raise("/fake/source", "/fake/link")
        self.mox.VerifyAll()
Beispiel #9
0
    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)
Beispiel #10
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)
Beispiel #11
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)
Beispiel #12
0
    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)
Beispiel #13
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)
Beispiel #14
0
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)
Beispiel #15
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)
Beispiel #16
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)
Beispiel #17
0
 def test_create_link_EEXIST(self):
     with mock.patch.object(os, "symlink", autospec=True) as symlink_mock:
         symlink_mock.side_effect = OSError(errno.EEXIST)
         utils.create_link_without_raise("/fake/source", "/fake/link")
         symlink_mock.assert_called_once_with("/fake/source", "/fake/link")
Beispiel #18
0
 def create_link(mac_path):
     ironic_utils.unlink_without_raise(mac_path)
     relative_source_path = os.path.relpath(pxe_config_file_path,
                                            os.path.dirname(mac_path))
     utils.create_link_without_raise(relative_source_path, mac_path)
Beispiel #19
0
 def test_create_link_EEXIST(self):
     with mock.patch.object(os, "symlink") as symlink_mock:
         symlink_mock.side_effect = OSError(errno.EEXIST)
         utils.create_link_without_raise("/fake/source", "/fake/link")
         symlink_mock.assert_called_once_with("/fake/source", "/fake/link")
Beispiel #20
0
 def test_create_link(self):
     with mock.patch.object(os, "symlink") as symlink_mock:
         symlink_mock.return_value = None
         utils.create_link_without_raise("/fake/source", "/fake/link")
         symlink_mock.assert_called_once_with("/fake/source", "/fake/link")
Beispiel #21
0
 def create_link(mac_path):
     utils.unlink_without_raise(mac_path)
     utils.create_link_without_raise(pxe_config_file_path, mac_path)
Beispiel #22
0
 def create_link(mac_path):
     ironic_utils.unlink_without_raise(mac_path)
     relative_source_path = os.path.relpath(
         pxe_config_file_path, os.path.dirname(mac_path))
     utils.create_link_without_raise(relative_source_path, mac_path)
Beispiel #23
0
 def create_link(mac_path):
     utils.unlink_without_raise(mac_path)
     utils.create_link_without_raise(pxe_config_file_path, mac_path)
Beispiel #24
0
 def test_create_link(self):
     with mock.patch.object(os, "symlink", autospec=True) as symlink_mock:
         symlink_mock.return_value = None
         utils.create_link_without_raise("/fake/source", "/fake/link")
         symlink_mock.assert_called_once_with("/fake/source", "/fake/link")
Beispiel #25
0
def build_instance_info_for_deploy(task):
    """Build instance_info necessary for deploying to a node.

    :param task: a TaskManager object containing the node
    :returns: a dictionary containing the properties to be updated
        in instance_info
    :raises: exception.ImageRefValidationFailed if image_source is not
        Glance href and is not HTTP(S) URL.
    """
    def validate_image_url(url, secret=False):
        """Validates image URL through the HEAD request.

        :param url: URL to be validated
        :param secret: if URL is secret (e.g. swift temp url),
            it will not be shown in logs.
        """
        try:
            image_service.HttpImageService().validate_href(url, secret)
        except exception.ImageRefValidationFailed as e:
            with excutils.save_and_reraise_exception():
                LOG.error(
                    "Agent deploy supports only HTTP(S) URLs as "
                    "instance_info['image_source'] or swift "
                    "temporary URL. Either the specified URL is not "
                    "a valid HTTP(S) URL or is not reachable "
                    "for node %(node)s. Error: %(msg)s", {
                        'node': node.uuid,
                        'msg': e
                    })

    node = task.node
    instance_info = node.instance_info
    iwdi = node.driver_internal_info.get('is_whole_disk_image')
    image_source = instance_info['image_source']

    if service_utils.is_glance_image(image_source):
        glance = image_service.GlanceImageService(context=task.context)
        image_info = glance.show(image_source)
        LOG.debug('Got image info: %(info)s for node %(node)s.', {
            'info': image_info,
            'node': node.uuid
        })
        if CONF.agent.image_download_source == 'swift':
            swift_temp_url = glance.swift_temp_url(image_info)
            validate_image_url(swift_temp_url, secret=True)
            instance_info['image_url'] = swift_temp_url
            instance_info['image_checksum'] = image_info['checksum']
            instance_info['image_disk_format'] = image_info['disk_format']
            instance_info['image_os_hash_algo'] = image_info['os_hash_algo']
            instance_info['image_os_hash_value'] = image_info['os_hash_value']
        else:
            # Ironic cache and serve images from httpboot server
            force_raw = direct_deploy_should_convert_raw_image(node)
            _, image_path = cache_instance_image(task.context,
                                                 node,
                                                 force_raw=force_raw)
            if force_raw:
                instance_info['image_disk_format'] = 'raw'
                # Standard behavior is for image_checksum to be MD5,
                # so if the hash algorithm is None, then we will use
                # sha256.
                os_hash_algo = image_info.get('os_hash_algo')
                if os_hash_algo == 'md5':
                    LOG.debug(
                        'Checksum calculation for image %(image)s is '
                        'set to \'%(algo)s\', changing to \'sha256\'', {
                            'algo': os_hash_algo,
                            'image': image_path
                        })
                    os_hash_algo = 'sha256'
                LOG.debug(
                    'Recalculating checksum for image %(image)s due to '
                    'image conversion.', {'image': image_path})
                instance_info['image_checksum'] = None
                hash_value = compute_image_checksum(image_path, os_hash_algo)
                instance_info['image_os_hash_algo'] = os_hash_algo
                instance_info['image_os_hash_value'] = hash_value
            else:
                instance_info['image_checksum'] = image_info['checksum']
                instance_info['image_disk_format'] = image_info['disk_format']
                instance_info['image_os_hash_algo'] = image_info[
                    'os_hash_algo']
                instance_info['image_os_hash_value'] = image_info[
                    'os_hash_value']

            # Create symlink and update image url
            symlink_dir = _get_http_image_symlink_dir_path()
            fileutils.ensure_tree(symlink_dir)
            symlink_path = _get_http_image_symlink_file_path(node.uuid)
            utils.create_link_without_raise(image_path, symlink_path)
            base_url = CONF.deploy.http_url
            if base_url.endswith('/'):
                base_url = base_url[:-1]
            http_image_url = '/'.join(
                [base_url, CONF.deploy.http_image_subdir, node.uuid])
            validate_image_url(http_image_url, secret=True)
            instance_info['image_url'] = http_image_url

        instance_info['image_container_format'] = (
            image_info['container_format'])
        instance_info['image_tags'] = image_info.get('tags', [])
        instance_info['image_properties'] = image_info['properties']

        if not iwdi:
            instance_info['kernel'] = image_info['properties']['kernel_id']
            instance_info['ramdisk'] = image_info['properties']['ramdisk_id']
    else:
        validate_image_url(image_source)
        instance_info['image_url'] = image_source

    if not iwdi:
        instance_info['image_type'] = 'partition'
        i_info = parse_instance_info(node)
        instance_info.update(i_info)
    else:
        instance_info['image_type'] = 'whole-disk-image'
    return instance_info