コード例 #1
0
ファイル: test_common.py プロジェクト: bharathshetty4/ironic
 def test_copy_image_to_web_server(self, copy_mock, chmod_mock):
     CONF.deploy.http_url = "http://x.y.z.a/webserver/"
     CONF.deploy.http_root = "/webserver"
     expected_url = "http://x.y.z.a/webserver/image-UUID"
     source = "tmp_image_file"
     destination = "image-UUID"
     image_path = "/webserver/image-UUID"
     actual_url = ilo_common.copy_image_to_web_server(source, destination)
     self.assertEqual(expected_url, actual_url)
     copy_mock.assert_called_once_with(source, image_path)
     chmod_mock.assert_called_once_with(image_path, 0o644)
コード例 #2
0
ファイル: firmware_processor.py プロジェクト: Tehsmash/ironic
def _extract_fw_from_file(node, target_file):
    """Extracts firmware image file.

    Extracts the firmware image file thru proliantutils and uploads it to the
    conductor webserver, if needed.
    :param node: an Ironic node object.
    :param target_file: firmware file to be extracted from
    :returns: tuple of:
                a) wrapper object of raw firmware image location
                b) a boolean, depending upon whether the raw firmware file was
                   already in raw format(same file remains, no need to extract)
                   or compact format (thereby extracted and hence different
                   file). If uploaded then, then also its a different file.
    :raises: ImageUploadFailed, if upload to web server fails.
    :raises: SwiftOperationError, if upload to Swift fails.
    :raises: IloOperationError, on failure to process firmware file.
    """
    ilo_object = ilo_common.get_ilo_object(node)

    try:
        # Note(deray): Based upon different iLO firmwares, the firmware file
        # which needs to be updated has to be either an http/https or a simple
        # file location. If it has to be a http/https location, then conductor
        # will take care of uploading the firmware file to web server or
        # swift (providing a temp url).
        fw_image_location, to_upload, is_extracted = (
            proliantutils_utils.process_firmware_image(target_file,
                                                       ilo_object))
    except (proliantutils_error.InvalidInputError,
            proliantutils_error.ImageExtractionFailed) as proliantutils_exc:
        operation = _("Firmware file extracting as part of manual cleaning")
        raise exception.IloOperationError(operation=operation,
                                          error=proliantutils_exc)

    is_different_file = is_extracted
    fw_image_filename = os.path.basename(fw_image_location)
    fw_image_location_obj = FirmwareImageLocation(fw_image_location,
                                                  fw_image_filename)
    if to_upload:
        is_different_file = True
        try:
            if CONF.ilo.use_web_server_for_images:
                # upload firmware image file to conductor webserver
                LOG.debug("For firmware update on node %(node)s, hosting "
                          "firmware file %(firmware_image)s on web server ...",
                          {'firmware_image': fw_image_location,
                           'node': node.uuid})
                fw_image_uploaded_url = ilo_common.copy_image_to_web_server(
                    fw_image_location, fw_image_filename)

                fw_image_location_obj.fw_image_location = fw_image_uploaded_url
                fw_image_location_obj.remove = types.MethodType(
                    _remove_webserver_based_me, fw_image_location_obj)
            else:
                # upload firmware image file to swift
                LOG.debug("For firmware update on node %(node)s, hosting "
                          "firmware file %(firmware_image)s on swift ...",
                          {'firmware_image': fw_image_location,
                           'node': node.uuid})
                fw_image_uploaded_url = ilo_common.copy_image_to_swift(
                    fw_image_location, fw_image_filename)

                fw_image_location_obj.fw_image_location = fw_image_uploaded_url
                fw_image_location_obj.remove = types.MethodType(
                    _remove_swift_based_me, fw_image_location_obj)
        finally:
            if is_extracted:
                # Note(deray): remove the file `fw_image_location` irrespective
                # of status of uploading (success or failure) and only if
                # extracted (and not passed as in plain binary format). If the
                # file is passed in binary format, then the invoking method
                # takes care of handling the deletion of the file.
                ilo_common.remove_single_or_list_of_files(fw_image_location)

        LOG.debug("For firmware update on node %(node)s, hosting firmware "
                  "file: %(fw_image_location)s ... done. Hosted firmware "
                  "file: %(fw_image_uploaded_url)s",
                  {'fw_image_location': fw_image_location, 'node': node.uuid,
                   'fw_image_uploaded_url': fw_image_uploaded_url})
    else:
        fw_image_location_obj.remove = types.MethodType(
            _remove_file_based_me, fw_image_location_obj)

    return fw_image_location_obj, is_different_file
コード例 #3
0
def _get_boot_iso(task, root_uuid):
    """This method returns a boot ISO to boot the node.

    It chooses one of the three options in the order as below:
    1. Does nothing if 'ilo_boot_iso' is present in node's instance_info and
       'boot_iso_created_in_web_server' is not set in 'driver_internal_info'.
    2. Image deployed has a meta-property 'boot_iso' in Glance. This should
       refer to the UUID of the boot_iso which exists in Glance.
    3. Generates a boot ISO on the fly using kernel and ramdisk mentioned in
       the image deployed. It uploads the generated boot ISO to Swift.

    :param task: a TaskManager instance containing the node to act on.
    :param root_uuid: the uuid of the root partition.
    :returns: boot ISO URL. Should be either of below:
        * A Swift object - It should be of format 'swift:<object-name>'. It is
          assumed that the image object is present in
          CONF.ilo.swift_ilo_container;
        * A Glance image - It should be format 'glance://<glance-image-uuid>'
          or just <glance-image-uuid>;
        * An HTTP URL.
        On error finding the boot iso, it returns None.
    :raises: MissingParameterValue, if any of the required parameters are
        missing in the node's driver_info or instance_info.
    :raises: InvalidParameterValue, if any of the parameters have invalid
        value in the node's driver_info or instance_info.
    :raises: SwiftOperationError, if operation with Swift fails.
    :raises: ImageCreationFailed, if creation of boot ISO failed.
    :raises: exception.ImageRefValidationFailed if ilo_boot_iso is not
        HTTP(S) URL.
    """
    LOG.debug("Trying to get a boot ISO to boot the baremetal node")

    # Option 1 - Check if user has provided ilo_boot_iso in node's
    # instance_info
    driver_internal_info = task.node.driver_internal_info
    boot_iso_created_in_web_server = (
        driver_internal_info.get('boot_iso_created_in_web_server'))

    if (task.node.instance_info.get('ilo_boot_iso')
            and not boot_iso_created_in_web_server):
        LOG.debug("Using ilo_boot_iso provided in node's instance_info")
        boot_iso = task.node.instance_info['ilo_boot_iso']
        if not service_utils.is_glance_image(boot_iso):
            try:
                image_service.HttpImageService().validate_href(boot_iso)
            except exception.ImageRefValidationFailed:
                with excutils.save_and_reraise_exception():
                    LOG.error("Virtual media deploy accepts only Glance "
                              "images or HTTP(S) URLs as "
                              "instance_info['ilo_boot_iso']. Either %s "
                              "is not a valid HTTP(S) URL or is "
                              "not reachable.", boot_iso)

        return task.node.instance_info['ilo_boot_iso']

    # Option 2 - Check if user has provided a boot_iso in Glance. If boot_iso
    # is a supported non-glance href execution will proceed to option 3.
    deploy_info = _parse_deploy_info(task.node)

    image_href = deploy_info['image_source']
    image_properties = (
        images.get_image_properties(
            task.context, image_href, ['boot_iso', 'kernel_id', 'ramdisk_id']))

    boot_iso_uuid = image_properties.get('boot_iso')
    kernel_href = (task.node.instance_info.get('kernel')
                   or image_properties.get('kernel_id'))
    ramdisk_href = (task.node.instance_info.get('ramdisk')
                    or image_properties.get('ramdisk_id'))

    if boot_iso_uuid:
        LOG.debug("Found boot_iso %s in Glance", boot_iso_uuid)
        return boot_iso_uuid

    if not kernel_href or not ramdisk_href:
        LOG.error("Unable to find kernel or ramdisk for "
                  "image %(image)s to generate boot ISO for %(node)s",
                  {'image': image_href, 'node': task.node.uuid})
        return

    # NOTE(rameshg87): Functionality to share the boot ISOs created for
    # similar instances (instances with same deployed image) is
    # not implemented as of now. Creation/Deletion of such a shared boot ISO
    # will require synchronisation across conductor nodes for the shared boot
    # ISO.  Such a synchronisation mechanism doesn't exist in ironic as of now.

    # Option 3 - Create boot_iso from kernel/ramdisk, upload to Swift
    # or web server and provide its name.
    deploy_iso_uuid = deploy_info['ilo_deploy_iso']
    boot_mode = boot_mode_utils.get_boot_mode_for_deploy(task.node)
    boot_iso_object_name = _get_boot_iso_object_name(task.node)
    kernel_params = ""
    if deploy_utils.get_boot_option(task.node) == "ramdisk":
        i_info = task.node.instance_info
        kernel_params = "root=/dev/ram0 text "
        kernel_params += i_info.get("ramdisk_kernel_arguments", "")
    else:
        kernel_params = CONF.pxe.pxe_append_params
    with tempfile.NamedTemporaryFile(dir=CONF.tempdir) as fileobj:
        boot_iso_tmp_file = fileobj.name
        images.create_boot_iso(task.context, boot_iso_tmp_file,
                               kernel_href, ramdisk_href,
                               deploy_iso_uuid, root_uuid,
                               kernel_params, boot_mode)

        if CONF.ilo.use_web_server_for_images:
            boot_iso_url = (
                ilo_common.copy_image_to_web_server(boot_iso_tmp_file,
                                                    boot_iso_object_name))
            driver_internal_info = task.node.driver_internal_info
            driver_internal_info['boot_iso_created_in_web_server'] = True
            task.node.driver_internal_info = driver_internal_info
            task.node.save()
            LOG.debug("Created boot_iso %(boot_iso)s for node %(node)s",
                      {'boot_iso': boot_iso_url, 'node': task.node.uuid})
            return boot_iso_url
        else:
            container = CONF.ilo.swift_ilo_container
            swift_api = swift.SwiftAPI()
            swift_api.create_object(container, boot_iso_object_name,
                                    boot_iso_tmp_file)

            LOG.debug("Created boot_iso %s in Swift", boot_iso_object_name)
            return 'swift:%s' % boot_iso_object_name
コード例 #4
0
ファイル: boot.py プロジェクト: michaeltchapman/ironic
def _get_boot_iso(task, root_uuid):
    """This method returns a boot ISO to boot the node.

    It chooses one of the three options in the order as below:
    1. Does nothing if 'ilo_boot_iso' is present in node's instance_info and
       'boot_iso_created_in_web_server' is not set in 'driver_internal_info'.
    2. Image deployed has a meta-property 'boot_iso' in Glance. This should
       refer to the UUID of the boot_iso which exists in Glance.
    3. Generates a boot ISO on the fly using kernel and ramdisk mentioned in
       the image deployed. It uploads the generated boot ISO to Swift.

    :param task: a TaskManager instance containing the node to act on.
    :param root_uuid: the uuid of the root partition.
    :returns: boot ISO URL. Should be either of below:
        * A Swift object - It should be of format 'swift:<object-name>'. It is
          assumed that the image object is present in
          CONF.ilo.swift_ilo_container;
        * A Glance image - It should be format 'glance://<glance-image-uuid>'
          or just <glance-image-uuid>;
        * An HTTP URL.
        On error finding the boot iso, it returns None.
    :raises: MissingParameterValue, if any of the required parameters are
        missing in the node's driver_info or instance_info.
    :raises: InvalidParameterValue, if any of the parameters have invalid
        value in the node's driver_info or instance_info.
    :raises: SwiftOperationError, if operation with Swift fails.
    :raises: ImageCreationFailed, if creation of boot ISO failed.
    :raises: exception.ImageRefValidationFailed if ilo_boot_iso is not
        HTTP(S) URL.
    """
    LOG.debug("Trying to get a boot ISO to boot the baremetal node")

    # Option 1 - Check if user has provided ilo_boot_iso in node's
    # instance_info
    driver_internal_info = task.node.driver_internal_info
    boot_iso_created_in_web_server = (
        driver_internal_info.get('boot_iso_created_in_web_server'))

    if (task.node.instance_info.get('ilo_boot_iso')
            and not boot_iso_created_in_web_server):
        LOG.debug("Using ilo_boot_iso provided in node's instance_info")
        boot_iso = task.node.instance_info['ilo_boot_iso']
        if not service_utils.is_glance_image(boot_iso):
            try:
                image_service.HttpImageService().validate_href(boot_iso)
            except exception.ImageRefValidationFailed:
                with excutils.save_and_reraise_exception():
                    LOG.error("Virtual media deploy accepts only Glance "
                              "images or HTTP(S) URLs as "
                              "instance_info['ilo_boot_iso']. Either %s "
                              "is not a valid HTTP(S) URL or is "
                              "not reachable.", boot_iso)

        return task.node.instance_info['ilo_boot_iso']

    # Option 2 - Check if user has provided a boot_iso in Glance. If boot_iso
    # is a supported non-glance href execution will proceed to option 3.
    deploy_info = _parse_deploy_info(task.node)

    image_href = deploy_info['image_source']
    image_properties = (
        images.get_image_properties(
            task.context, image_href, ['boot_iso', 'kernel_id', 'ramdisk_id']))

    boot_iso_uuid = image_properties.get('boot_iso')
    kernel_href = (task.node.instance_info.get('kernel')
                   or image_properties.get('kernel_id'))
    ramdisk_href = (task.node.instance_info.get('ramdisk')
                    or image_properties.get('ramdisk_id'))

    if boot_iso_uuid:
        LOG.debug("Found boot_iso %s in Glance", boot_iso_uuid)
        return boot_iso_uuid

    if not kernel_href or not ramdisk_href:
        LOG.error("Unable to find kernel or ramdisk for "
                  "image %(image)s to generate boot ISO for %(node)s",
                  {'image': image_href, 'node': task.node.uuid})
        return

    # NOTE(rameshg87): Functionality to share the boot ISOs created for
    # similar instances (instances with same deployed image) is
    # not implemented as of now. Creation/Deletion of such a shared boot ISO
    # will require synchronisation across conductor nodes for the shared boot
    # ISO.  Such a synchronisation mechanism doesn't exist in ironic as of now.

    # Option 3 - Create boot_iso from kernel/ramdisk, upload to Swift
    # or web server and provide its name.
    deploy_iso_uuid = deploy_info['ilo_deploy_iso']
    boot_mode = boot_mode_utils.get_boot_mode(task.node)
    boot_iso_object_name = _get_boot_iso_object_name(task.node)
    kernel_params = ""
    if deploy_utils.get_boot_option(task.node) == "ramdisk":
        i_info = task.node.instance_info
        kernel_params = "root=/dev/ram0 text "
        kernel_params += i_info.get("ramdisk_kernel_arguments", "")
    else:
        kernel_params = CONF.pxe.pxe_append_params
    with tempfile.NamedTemporaryFile(dir=CONF.tempdir) as fileobj:
        boot_iso_tmp_file = fileobj.name
        images.create_boot_iso(task.context, boot_iso_tmp_file,
                               kernel_href, ramdisk_href,
                               deploy_iso_href=deploy_iso_uuid,
                               root_uuid=root_uuid,
                               kernel_params=kernel_params,
                               boot_mode=boot_mode)

        if CONF.ilo.use_web_server_for_images:
            boot_iso_url = (
                ilo_common.copy_image_to_web_server(boot_iso_tmp_file,
                                                    boot_iso_object_name))
            driver_internal_info = task.node.driver_internal_info
            driver_internal_info['boot_iso_created_in_web_server'] = True
            task.node.driver_internal_info = driver_internal_info
            task.node.save()
            LOG.debug("Created boot_iso %(boot_iso)s for node %(node)s",
                      {'boot_iso': boot_iso_url, 'node': task.node.uuid})
            return boot_iso_url
        else:
            container = CONF.ilo.swift_ilo_container
            swift_api = swift.SwiftAPI()
            swift_api.create_object(container, boot_iso_object_name,
                                    boot_iso_tmp_file)

            LOG.debug("Created boot_iso %s in Swift", boot_iso_object_name)
            return 'swift:%s' % boot_iso_object_name
コード例 #5
0
def _extract_fw_from_file(node, target_file):
    """Extracts firmware image file.

    Extracts the firmware image file thru proliantutils and uploads it to the
    conductor webserver, if needed.
    :param node: an Ironic node object.
    :param target_file: firmware file to be extracted from
    :returns: tuple of:
                a) wrapper object of raw firmware image location
                b) a boolean, depending upon whether the raw firmware file was
                   already in raw format(same file remains, no need to extract)
                   or compact format (thereby extracted and hence different
                   file). If uploaded then, then also its a different file.
    :raises: ImageUploadFailed, if upload to web server fails.
    :raises: SwiftOperationError, if upload to Swift fails.
    :raises: IloOperationError, on failure to process firmware file.
    """
    ilo_object = ilo_common.get_ilo_object(node)

    try:
        # Note(deray): Based upon different iLO firmwares, the firmware file
        # which needs to be updated has to be either an http/https or a simple
        # file location. If it has to be a http/https location, then conductor
        # will take care of uploading the firmware file to web server or
        # swift (providing a temp url).
        fw_image_location, to_upload, is_extracted = (
            proliantutils_utils.process_firmware_image(target_file,
                                                       ilo_object))
    except (proliantutils_error.InvalidInputError,
            proliantutils_error.ImageExtractionFailed) as proliantutils_exc:
        operation = _("Firmware file extracting as part of manual cleaning")
        raise exception.IloOperationError(operation=operation,
                                          error=proliantutils_exc)

    is_different_file = is_extracted
    fw_image_filename = os.path.basename(fw_image_location)
    fw_image_location_obj = FirmwareImageLocation(fw_image_location,
                                                  fw_image_filename)
    if to_upload:
        is_different_file = True
        try:
            if CONF.ilo.use_web_server_for_images:
                # upload firmware image file to conductor webserver
                LOG.debug(
                    "For firmware update on node %(node)s, hosting "
                    "firmware file %(firmware_image)s on web server ...", {
                        'firmware_image': fw_image_location,
                        'node': node.uuid
                    })
                fw_image_uploaded_url = ilo_common.copy_image_to_web_server(
                    fw_image_location, fw_image_filename)

                fw_image_location_obj.fw_image_location = fw_image_uploaded_url
                fw_image_location_obj.remove = types.MethodType(
                    _remove_webserver_based_me, fw_image_location_obj)
            else:
                # upload firmware image file to swift
                LOG.debug(
                    "For firmware update on node %(node)s, hosting "
                    "firmware file %(firmware_image)s on swift ...", {
                        'firmware_image': fw_image_location,
                        'node': node.uuid
                    })
                fw_image_uploaded_url = ilo_common.copy_image_to_swift(
                    fw_image_location, fw_image_filename)

                fw_image_location_obj.fw_image_location = fw_image_uploaded_url
                fw_image_location_obj.remove = types.MethodType(
                    _remove_swift_based_me, fw_image_location_obj)
        finally:
            if is_extracted:
                # Note(deray): remove the file `fw_image_location` irrespective
                # of status of uploading (success or failure) and only if
                # extracted (and not passed as in plain binary format). If the
                # file is passed in binary format, then the invoking method
                # takes care of handling the deletion of the file.
                ilo_common.remove_single_or_list_of_files(fw_image_location)

        LOG.debug(
            "For firmware update on node %(node)s, hosting firmware "
            "file: %(fw_image_location)s ... done. Hosted firmware "
            "file: %(fw_image_uploaded_url)s", {
                'fw_image_location': fw_image_location,
                'node': node.uuid,
                'fw_image_uploaded_url': fw_image_uploaded_url
            })
    else:
        fw_image_location_obj.remove = types.MethodType(
            _remove_file_based_me, fw_image_location_obj)

    return fw_image_location_obj, is_different_file