예제 #1
0
    def _get_flow(self, task):
        try:
            task_input = script_utils.unpack_task_input(task)
            uri = script_utils.validate_location_uri(
                task_input.get('import_from'))

            kwds = {
                'uri': uri,
                'task_id': task.task_id,
                'task_type': task.type,
                'context': self.context,
                'task_repo': self.task_repo,
                'image_repo': self.image_repo,
                'image_factory': self.image_factory
            }

            return driver.DriverManager('glance.flows',
                                        task.type,
                                        invoke_on_load=True,
                                        invoke_kwds=kwds).driver
        except urllib.error.URLError as exc:
            raise exception.ImportTaskError(message=exc.reason)
        except exception.BadStoreUri as exc:
            raise exception.ImportTaskError(message=exc.msg)
        except RuntimeError:
            raise NotImplementedError()
예제 #2
0
    def _get_flow(self, task):
        try:
            task_input = script_utils.unpack_task_input(task)

            kwds = {
                'task_id': task.task_id,
                'task_type': task.type,
                'context': self.context,
                'task_repo': self.task_repo,
                'image_repo': self.image_repo,
                'image_factory': self.image_factory,
                'backend': task_input.get('backend')
            }

            if self.admin_repo:
                kwds['admin_repo'] = self.admin_repo

            if task.type == "import":
                uri = script_utils.validate_location_uri(
                    task_input.get('import_from'))
                kwds['uri'] = uri
            if task.type == 'api_image_import':
                kwds['image_id'] = task_input['image_id']
                kwds['import_req'] = task_input['import_req']
            return driver.DriverManager('glance.flows',
                                        task.type,
                                        invoke_on_load=True,
                                        invoke_kwds=kwds).driver
        except urllib.error.URLError as exc:
            raise exception.ImportTaskError(message=exc.reason)
        except (exception.BadStoreUri, exception.Invalid) as exc:
            raise exception.ImportTaskError(message=exc.msg)
        except RuntimeError:
            raise NotImplementedError()
예제 #3
0
    def execute(self):
        """Create temp file into store and return path to it

        :param image_id: Glance Image ID
        """
        # NOTE(jokke): We've decided to use staging area for this task as
        # a way to expect users to configure a local store for pre-import
        # works on the image to happen.
        #
        # While using any path should be "technically" fine, it's not what
        # we recommend as the best solution. For more details on this, please
        # refer to the comment in the `_ImportToStore.execute` method.
        try:
            data = script_utils.get_image_data_iter(self.uri)
        except Exception as e:
            with excutils.save_and_reraise_exception():
                LOG.error("Task %(task_id)s failed with exception %(error)s",
                          {"error": encodeutils.exception_to_unicode(e),
                           "task_id": self.task_id})

        self._path, bytes_written = self.store.add(self.image_id, data, 0)[0:2]
        try:
            content_length = int(data.headers['content-length'])
            if bytes_written != content_length:
                msg = (_("Task %(task_id)s failed because downloaded data "
                         "size %(data_size)i is different from expected %("
                         "expected)i") %
                       {"task_id": self.task_id, "data_size": bytes_written,
                        "expected": content_length})
                raise exception.ImportTaskError(msg)
        except (KeyError, ValueError):
            pass
        return self._path
예제 #4
0
    def _execute(self, action, file_path):
        self.last_status = timeutils.now()

        if action.image_status == "deleted":
            raise exception.ImportTaskError("Image has been deleted, aborting"
                                            " import.")
        try:
            action.set_image_data(file_path or self.uri,
                                  self.task_id,
                                  backend=self.backend,
                                  set_active=self.set_active,
                                  callback=self._status_callback)
        # NOTE(yebinama): set_image_data catches Exception and raises from
        # them. Can't be more specific on exceptions catched.
        except Exception:
            if self.all_stores_must_succeed:
                raise
            msg = (_("%(task_id)s of %(task_type)s failed but since "
                     "all_stores_must_succeed is set to false, continue.") % {
                         'task_id': self.task_id,
                         'task_type': self.task_type
                     })
            LOG.warning(msg)
            if self.backend is not None:
                action.add_failed_stores([self.backend])

        if self.backend is not None:
            action.remove_importing_stores([self.backend])
예제 #5
0
    def execute(self, file_path=None):
        """Bringing the imported image to back end store

        :param image_id: Glance Image ID
        :param file_path: path to the image file
        """
        # NOTE(flaper87): Let's dance... and fall
        #
        # Unfortunatelly, because of the way our domain layers work and
        # the checks done in the FS store, we can't simply rename the file
        # and set the location. To do that, we'd have to duplicate the logic
        # of every and each of the domain factories (quota, location, etc)
        # and we'd also need to hack the FS store to prevent it from raising
        # a "duplication path" error. I'd rather have this task copying the
        # image bits one more time than duplicating all that logic.
        #
        # Since I don't think this should be the definitive solution, I'm
        # leaving the code below as a reference for what should happen here
        # once the FS store and domain code will be able to handle this case.
        #
        # if file_path is None:
        #    image_import.set_image_data(image, self.uri, None)
        #    return

        # NOTE(flaper87): Don't assume the image was stored in the
        # work_dir. Think in the case this path was provided by another task.
        # Also, lets try to neither assume things nor create "logic"
        # dependencies between this task and `_ImportToFS`
        #
        # base_path = os.path.dirname(file_path.split("file://")[-1])

        # NOTE(flaper87): Hopefully just scenarios #3 and #4. I say
        # hopefully because nothing prevents the user to use the same
        # FS store path as a work dir
        #
        # image_path = os.path.join(base_path, image_id)
        #
        # if (base_path == CONF.glance_store.filesystem_store_datadir or
        #      base_path in CONF.glance_store.filesystem_store_datadirs):
        #     os.rename(file_path, image_path)
        #
        # image_import.set_image_data(image, image_path, None)

        # NOTE(jokke): The different options here are kind of pointless as we
        # will need the file path anyways for our delete workflow for now.
        # For future proofing keeping this as is.
        image = self.image_repo.get(self.image_id)
        if image.status == "deleted":
            raise exception.ImportTaskError("Image has been deleted, aborting"
                                            " import.")
        try:
            image_import.set_image_data(image,
                                        file_path or self.uri,
                                        self.task_id,
                                        backend=self.backend,
                                        set_active=self.set_active)
        # NOTE(yebinama): set_image_data catches Exception and raises from
        # them. Can't be more specific on exceptions catched.
        except Exception:
            if not self.allow_failure:
                raise
            msg = (_("%(task_id)s of %(task_type)s failed but since "
                     "allow_failure is set to true, continue.") % {
                         'task_id': self.task_id,
                         'task_type': self.task_type
                     })
            LOG.warning(msg)
            if self.backend is not None:
                failed_import = image.extra_properties.get(
                    'os_glance_failed_import', '').split(',')
                failed_import.append(self.backend)
                image.extra_properties['os_glance_failed_import'] = ','.join(
                    failed_import)
        if self.backend is not None:
            importing = image.extra_properties.get(
                'os_glance_importing_to_stores', '').split(',')
            try:
                importing.remove(self.backend)
                image.extra_properties[
                    'os_glance_importing_to_stores'] = ','.join(importing)
            except ValueError:
                LOG.debug(
                    "Store %s not found in property "
                    "os_glance_importing_to_stores.", self.backend)
        # NOTE(flaper87): We need to save the image again after
        # the locations have been set in the image.
        self.image_repo.save(image)