def _prepare_floppy_image(task, params): """Prepares the floppy image for passing the parameters. This method prepares a temporary vfat filesystem image, which contains the parameters to be passed to the ramdisk. Then it uploads the file NFS or CIFS server. :param task: a TaskManager instance containing the node to act on. :param params: a dictionary containing 'parameter name'->'value' mapping to be passed to the deploy ramdisk via the floppy image. :returns: floppy image filename :raises: ImageCreationFailed, if it failed while creating the floppy image. :raises: IRMCOperationError, if copying floppy image file failed. """ floppy_filename = _get_floppy_image_name(task.node) floppy_fullpathname = os.path.join(CONF.irmc.remote_image_share_root, floppy_filename) with tempfile.NamedTemporaryFile() as vfat_image_tmpfile_obj: images.create_vfat_image(vfat_image_tmpfile_obj.name, parameters=params) try: shutil.copyfile(vfat_image_tmpfile_obj.name, floppy_fullpathname) except IOError as e: operation = _("Copying floppy image file") raise exception.IRMCOperationError(operation=operation, error=e) return floppy_filename
def _prepare_floppy_image(task, params): """Prepares the floppy image for passing the parameters. This method prepares a temporary vfat filesystem image, which contains the parameters to be passed to the ramdisk. Then it uploads the file NFS or CIFS server. :param task: a TaskManager instance containing the node to act on. :param params: a dictionary containing 'parameter name'->'value' mapping to be passed to the deploy ramdisk via the floppy image. :returns: floppy image filename :raises: ImageCreationFailed, if it failed while creating the floppy image. :raises: IRMCOperationError, if copying floppy image file failed. """ floppy_filename = _get_floppy_image_name(task.node) floppy_fullpathname = os.path.join( CONF.irmc.remote_image_share_root, floppy_filename) with tempfile.NamedTemporaryFile() as vfat_image_tmpfile_obj: images.create_vfat_image(vfat_image_tmpfile_obj.name, parameters=params) try: shutil.copyfile(vfat_image_tmpfile_obj.name, floppy_fullpathname) except IOError as e: operation = _("Copying floppy image file") raise exception.IRMCOperationError( operation=operation, error=e) return floppy_filename
def test_create_vfat_image(self, mkfs_mock, mount_mock, umount_mock, dd_mock, write_mock, tempdir_mock, create_root_fs_mock): mock_file_handle = mock.MagicMock(spec=file) mock_file_handle.__enter__.return_value = 'tempdir' tempdir_mock.return_value = mock_file_handle parameters = {'p1': 'v1'} files_info = {'a': 'b'} images.create_vfat_image('tgt_file', parameters=parameters, files_info=files_info, parameters_file='qwe', fs_size_kib=1000) dd_mock.assert_called_once_with('/dev/zero', 'tgt_file', 'count=1', 'bs=1000KiB') mkfs_mock.assert_called_once_with('vfat', 'tgt_file', label="ir-vfd-dev") mount_mock.assert_called_once_with('tgt_file', 'tempdir', '-o', 'umask=0') parameters_file_path = os.path.join('tempdir', 'qwe') write_mock.assert_called_once_with(parameters_file_path, 'p1=v1') create_root_fs_mock.assert_called_once_with('tempdir', files_info) umount_mock.assert_called_once_with('tempdir')
def _prepare_floppy_image(task, params): """Prepares the floppy image for passing the parameters. This method prepares a temporary vfat filesystem image. Then it adds a file into the image which contains the parameters to be passed to the ramdisk. After adding the parameters, it then uploads the file either to Swift in 'swift_ilo_container', setting it to auto-expire after 'swift_object_expiry_timeout' seconds or in web server. Then it returns the temp url for the Swift object or the http url for the uploaded floppy image depending upon value of CONF.ilo.use_web_server_for_images. :param task: a TaskManager instance containing the node to act on. :param params: a dictionary containing 'parameter name'->'value' mapping to be passed to the deploy ramdisk via the floppy image. :raises: ImageCreationFailed, if it failed while creating the floppy image. :raises: ImageUploadFailed, if copying the source file to the web server fails. :raises: SwiftOperationError, if any operation with Swift fails. :returns: the HTTP image URL or the Swift temp url for the floppy image. """ with tempfile.NamedTemporaryFile( dir=CONF.tempdir) as vfat_image_tmpfile_obj: vfat_image_tmpfile = vfat_image_tmpfile_obj.name images.create_vfat_image(vfat_image_tmpfile, parameters=params) object_name = _get_floppy_image_name(task.node) if CONF.ilo.use_web_server_for_images: image_url = copy_image_to_web_server(vfat_image_tmpfile, object_name) else: image_url = copy_image_to_swift(vfat_image_tmpfile, object_name) return image_url
def test_create_vfat_image(self, mkfs_mock, mount_mock, umount_mock, dd_mock, write_mock, tempdir_mock, create_root_fs_mock): mock_file_handle = mock.MagicMock(spec=file) mock_file_handle.__enter__.return_value = 'tempdir' tempdir_mock.return_value = mock_file_handle parameters = {'p1': 'v1'} files_info = {'a': 'b'} images.create_vfat_image('tgt_file', parameters=parameters, files_info=files_info, parameters_file='qwe', fs_size_kib=1000) dd_mock.assert_called_once_with('/dev/zero', 'tgt_file', 'count=1', 'bs=1000KiB') mkfs_mock.assert_called_once_with('vfat', 'tgt_file') mount_mock.assert_called_once_with('tgt_file', 'tempdir', '-o', 'umask=0') parameters_file_path = os.path.join('tempdir', 'qwe') write_mock.assert_called_once_with(parameters_file_path, 'p1=v1') create_root_fs_mock.assert_called_once_with('tempdir', files_info) umount_mock.assert_called_once_with('tempdir')
def _prepare_floppy_image(task, params): """Prepares the floppy image for passing the parameters. This method prepares a temporary vfat filesystem image. Then it adds two files into the image - one containing the authentication token and the other containing the parameters to be passed to the ramdisk. Then it uploads the file to Swift in 'swift_ilo_container', setting it to auto-expire after 'swift_object_expiry_timeout' seconds. Then it returns the temp url for the Swift object. :param task: a TaskManager instance containing the node to act on. :param params: a dictionary containing 'parameter name'->'value' mapping to be passed to the deploy ramdisk via the floppy image. :raises: ImageCreationFailed, if it failed while creating the floppy image. :raises: SwiftOperationError, if any operation with Swift fails. :returns: the Swift temp url for the floppy image. """ with tempfile.NamedTemporaryFile() as vfat_image_tmpfile_obj: files_info = {} token_tmpfile_obj = None vfat_image_tmpfile = vfat_image_tmpfile_obj.name # If auth_strategy is noauth, then no need to write token into # the image file. if task.context.auth_token: token_tmpfile_obj = tempfile.NamedTemporaryFile() token_tmpfile = token_tmpfile_obj.name utils.write_to_file(token_tmpfile, task.context.auth_token) files_info[token_tmpfile] = 'token' try: images.create_vfat_image(vfat_image_tmpfile, files_info=files_info, parameters=params) finally: if token_tmpfile_obj: token_tmpfile_obj.close() container = CONF.ilo.swift_ilo_container object_name = _get_floppy_image_name(task.node) timeout = CONF.ilo.swift_object_expiry_timeout object_headers = {'X-Delete-After': timeout} swift_api = swift.SwiftAPI() swift_api.create_object(container, object_name, vfat_image_tmpfile, object_headers=object_headers) temp_url = swift_api.get_temp_url(container, object_name, timeout) LOG.debug( "Uploaded floppy image %(object_name)s to %(container)s " "for deployment.", { 'object_name': object_name, 'container': container }) return temp_url
def _prepare_floppy_image(cls, task, params=None): """Prepares the floppy image for passing the parameters. This method prepares a temporary VFAT filesystem image and adds a file into the image which contains parameters to be passed to the ramdisk. Then this method uploads built image to Swift '[redfish]swift_container', setting it to auto expire after '[redfish]swift_object_expiry_timeout' seconds. Finally, a temporary Swift URL is returned addressing Swift object just created. :param task: a TaskManager instance containing the node to act on. :param params: a dictionary containing 'parameter name'->'value' mapping to be passed to deploy or rescue image via floppy image. :raises: ImageCreationFailed, if it failed while creating the floppy image. :raises: SwiftOperationError, if any operation with Swift fails. :returns: image URL for the floppy image. """ object_name = cls._get_floppy_image_name(task.node) container = CONF.redfish.swift_container timeout = CONF.redfish.swift_object_expiry_timeout object_headers = {'X-Delete-After': str(timeout)} swift_api = swift.SwiftAPI() LOG.debug("Trying to create floppy image for node " "%(node)s", {'node': task.node.uuid}) with tempfile.NamedTemporaryFile( dir=CONF.tempdir, suffix='.img') as vfat_image_tmpfile_obj: vfat_image_tmpfile = vfat_image_tmpfile_obj.name images.create_vfat_image(vfat_image_tmpfile, parameters=params) swift_api.create_object(container, object_name, vfat_image_tmpfile, object_headers=object_headers) image_url = swift_api.get_temp_url(container, object_name, timeout) image_url = cls._append_filename_param(image_url, 'bootme.img') LOG.debug( "Created floppy image %(name)s in Swift for node %(node)s, " "exposed as temporary URL " "%(url)s", { 'node': task.node.uuid, 'name': object_name, 'url': image_url }) return image_url
def _prepare_floppy_image(task, params): """Prepares the floppy image for passing the parameters. This method prepares a temporary vfat filesystem image. Then it adds two files into the image - one containing the authentication token and the other containing the parameters to be passed to the ramdisk. Then it uploads the file to Swift in 'swift_ilo_container', setting it to auto-expire after 'swift_object_expiry_timeout' seconds. Then it returns the temp url for the Swift object. :param task: a TaskManager instance containing the node to act on. :param params: a dictionary containing 'parameter name'->'value' mapping to be passed to the deploy ramdisk via the floppy image. :raises: ImageCreationFailed, if it failed while creating the floppy image. :raises: SwiftOperationError, if any operation with Swift fails. :returns: the Swift temp url for the floppy image. """ with tempfile.NamedTemporaryFile() as vfat_image_tmpfile_obj: files_info = {} token_tmpfile_obj = None vfat_image_tmpfile = vfat_image_tmpfile_obj.name # If auth_strategy is noauth, then no need to write token into # the image file. if task.context.auth_token: token_tmpfile_obj = tempfile.NamedTemporaryFile() token_tmpfile = token_tmpfile_obj.name utils.write_to_file(token_tmpfile, task.context.auth_token) files_info[token_tmpfile] = 'token' try: images.create_vfat_image(vfat_image_tmpfile, files_info=files_info, parameters=params) finally: if token_tmpfile_obj: token_tmpfile_obj.close() container = CONF.ilo.swift_ilo_container object_name = _get_floppy_image_name(task.node) timeout = CONF.ilo.swift_object_expiry_timeout object_headers = {'X-Delete-After': timeout} swift_api = swift.SwiftAPI() swift_api.create_object(container, object_name, vfat_image_tmpfile, object_headers=object_headers) temp_url = swift_api.get_temp_url(container, object_name, timeout) LOG.debug("Uploaded floppy image %(object_name)s to %(container)s " "for deployment.", {'object_name': object_name, 'container': container}) return temp_url
def _prepare_floppy_image(task, params): """Prepares the floppy image for passing the parameters. This method prepares a temporary vfat filesystem image. Then it adds a file into the image which contains the parameters to be passed to the ramdisk. After adding the parameters, it then uploads the file either to Swift in 'swift_ilo_container', setting it to auto-expire after 'swift_object_expiry_timeout' seconds or in web server. Then it returns the temp url for the Swift object or the http url for the uploaded floppy image depending upon value of CONF.ilo.use_web_server_for_images. :param task: a TaskManager instance containing the node to act on. :param params: a dictionary containing 'parameter name'->'value' mapping to be passed to the deploy ramdisk via the floppy image. :raises: ImageCreationFailed, if it failed while creating the floppy image. :raises: SwiftOperationError, if any operation with Swift fails. :returns: the Swift temp url for the floppy image. """ with tempfile.NamedTemporaryFile( dir=CONF.tempdir) as vfat_image_tmpfile_obj: vfat_image_tmpfile = vfat_image_tmpfile_obj.name images.create_vfat_image(vfat_image_tmpfile, parameters=params) object_name = _get_floppy_image_name(task.node) if CONF.ilo.use_web_server_for_images: image_url = copy_image_to_web_server(vfat_image_tmpfile, object_name) return image_url else: container = CONF.ilo.swift_ilo_container timeout = CONF.ilo.swift_object_expiry_timeout object_headers = {'X-Delete-After': timeout} swift_api = swift.SwiftAPI() swift_api.create_object(container, object_name, vfat_image_tmpfile, object_headers=object_headers) temp_url = swift_api.get_temp_url(container, object_name, timeout) LOG.debug( "Uploaded floppy image %(object_name)s to %(container)s " "for deployment.", { 'object_name': object_name, 'container': container }) return temp_url
def prepare_floppy_image(task, params=None): """Prepares the floppy image for passing the parameters. This method prepares a temporary VFAT filesystem image and adds a file into the image which contains parameters to be passed to the ramdisk. Then this method uploads built image to Swift '[redfish]swift_container', setting it to auto expire after '[redfish]swift_object_expiry_timeout' seconds. Finally, a temporary Swift URL is returned addressing Swift object just created. :param task: a TaskManager instance containing the node to act on. :param params: a dictionary containing 'parameter name'->'value' mapping to be passed to deploy or rescue image via floppy image. :raises: ImageCreationFailed, if it failed while creating the floppy image. :raises: SwiftOperationError, if any operation with Swift fails. :returns: image URL for the floppy image. """ object_name = _get_name(task.node, prefix='image') params = override_api_url(params) LOG.debug("Trying to create floppy image for node " "%(node)s", {'node': task.node.uuid}) with tempfile.NamedTemporaryFile(dir=CONF.tempdir, suffix='.img') as vfat_image_tmpfile_obj: vfat_image_tmpfile = vfat_image_tmpfile_obj.name images.create_vfat_image(vfat_image_tmpfile, parameters=params) img_handler = ImageHandler(task.node.driver) image_url = img_handler.publish_image(vfat_image_tmpfile, object_name) LOG.debug( "Created floppy image %(name)s in Swift for node %(node)s, " "exposed as temporary URL " "%(url)s", { 'node': task.node.uuid, 'name': object_name, 'url': image_url }) return image_url
def _prepare_floppy_image(task, params): """Prepares the floppy image for passing the parameters. This method prepares a temporary vfat filesystem image. Then it adds a file into the image which contains the parameters to be passed to the ramdisk. After adding the parameters, it then uploads the file either to Swift in 'swift_ilo_container', setting it to auto-expire after 'swift_object_expiry_timeout' seconds or in web server. Then it returns the temp url for the Swift object or the http url for the uploaded floppy image depending upon value of CONF.ilo.use_web_server_for_images. :param task: a TaskManager instance containing the node to act on. :param params: a dictionary containing 'parameter name'->'value' mapping to be passed to the deploy ramdisk via the floppy image. :raises: ImageCreationFailed, if it failed while creating the floppy image. :raises: SwiftOperationError, if any operation with Swift fails. :returns: the Swift temp url for the floppy image. """ with tempfile.NamedTemporaryFile( dir=CONF.tempdir) as vfat_image_tmpfile_obj: vfat_image_tmpfile = vfat_image_tmpfile_obj.name images.create_vfat_image(vfat_image_tmpfile, parameters=params) object_name = _get_floppy_image_name(task.node) if CONF.ilo.use_web_server_for_images: image_url = copy_image_to_web_server(vfat_image_tmpfile, object_name) return image_url else: container = CONF.ilo.swift_ilo_container timeout = CONF.ilo.swift_object_expiry_timeout object_headers = {'X-Delete-After': timeout} swift_api = swift.SwiftAPI() swift_api.create_object(container, object_name, vfat_image_tmpfile, object_headers=object_headers) temp_url = swift_api.get_temp_url(container, object_name, timeout) LOG.debug("Uploaded floppy image %(object_name)s to %(container)s " "for deployment.", {'object_name': object_name, 'container': container}) return temp_url
def test_create_vfat_image( self, mkfs_mock, mount_mock, umount_mock, dd_mock, write_mock, tempdir_mock, create_root_fs_mock ): mock_file_handle = mock.MagicMock(spec=file) mock_file_handle.__enter__.return_value = "tempdir" tempdir_mock.return_value = mock_file_handle parameters = {"p1": "v1"} files_info = {"a": "b"} images.create_vfat_image( "tgt_file", parameters=parameters, files_info=files_info, parameters_file="qwe", fs_size_kib=1000 ) dd_mock.assert_called_once_with("/dev/zero", "tgt_file", "count=1", "bs=1000KiB") mkfs_mock.assert_called_once_with("vfat", "tgt_file", label="ir-vfd-dev") mount_mock.assert_called_once_with("tgt_file", "tempdir", "-o", "umask=0") parameters_file_path = os.path.join("tempdir", "qwe") write_mock.assert_called_once_with(parameters_file_path, "p1=v1") create_root_fs_mock.assert_called_once_with("tempdir", files_info) umount_mock.assert_called_once_with("tempdir")
def prepare_deploy_iso(task, params, mode, d_info): """Prepare deploy or rescue ISO image Build bootable ISO out of `[driver_info]/deploy_kernel`/`[driver_info]/deploy_ramdisk` or `[driver_info]/rescue_kernel`/`[driver_info]/rescue_ramdisk` and `[driver_info]/bootloader`, then push built image up to Glance and return temporary Swift URL to the image. If network interface supplies network configuration (`network_data`), a new `configdrive` will be created with `network_data.json` inside, and eventually written down onto the boot ISO. :param task: a TaskManager instance containing the node to act on. :param params: a dictionary containing 'parameter name'->'value' mapping to be passed to kernel command line. :param mode: either 'deploy' or 'rescue'. :param d_info: Deployment information of the node :returns: bootable ISO HTTP URL. :raises: MissingParameterValue, if any of the required parameters are missing. :raises: InvalidParameterValue, if any of the parameters have invalid value. :raises: ImageCreationFailed, if creating ISO image failed. """ kernel_str = '%s_kernel' % mode ramdisk_str = '%s_ramdisk' % mode bootloader_str = 'bootloader' kernel_href = _find_param(kernel_str, d_info) ramdisk_href = _find_param(ramdisk_str, d_info) bootloader_href = _find_param(bootloader_str, d_info) # TODO(TheJulia): At some point we should support something like # boot_iso for the deploy interface, perhaps when we support config # injection. prepare_iso_image = functools.partial(_prepare_iso_image, task, kernel_href, ramdisk_href, bootloader_href=bootloader_href, params=params) network_data = task.driver.network.get_node_network_data(task) if network_data: with tempfile.NamedTemporaryFile(dir=CONF.tempdir, suffix='.iso') as metadata_fileobj: with open(metadata_fileobj.name, 'w') as f: json.dump(network_data, f, indent=2) files_info = { metadata_fileobj.name: 'openstack/latest/meta' 'data/network_data.json' } with tempfile.NamedTemporaryFile(dir=CONF.tempdir, suffix='.img') as cfgdrv_fileobj: images.create_vfat_image(cfgdrv_fileobj.name, files_info) configdrive_href = urlparse.urlunparse( ('file', '', cfgdrv_fileobj.name, '', '', '')) LOG.debug( "Built configdrive %(name)s out of network data " "for node %(node)s", { 'name': configdrive_href, 'node': task.node.uuid }) return prepare_iso_image(configdrive=configdrive_href) return prepare_iso_image()