Beispiel #1
0
class ContentUpload(SingleRepoAction):
    def __init__(self):
        super(ContentUpload, self).__init__()
        self.upload_api = ContentUploadAPI()

    description = _("upload content into a repository")

    @classmethod
    def get_content_data(cls, content_type, filepath):
        unit_key = metadata = None
        if content_type == "yum":
            try:
                unit_key, metadata = generate_rpm_data(filepath)
            except InvalidRPMError:
                print _("Invalid rpm '%s'. Please check the file and try again.") % filepath
        elif content_type == "puppet":
            try:
                unit_key, metadata = generate_puppet_data(filepath)
            except ExtractionException:
                print _(
                    "Invalid puppet module '%s'. Please make sure the file is valid and is named "
                    + "author-name-version.tar.gz (eg: puppetlabs-ntp-2.0.1.tar.gz)."
                ) % filepath

        return unit_key, metadata

    def setup_parser(self, parser):
        parser.add_option("--repo_id", dest="repo_id", help=_("repository ID (required)"))
        parser.add_option("--repo", dest="repo", help=_("repository name"))
        parser.add_option(
            "--filepath", dest="filepath", help=_("path of file or directory of files to upload (required)")
        )
        parser.add_option(
            "--content_type", dest="content_type", help=_("type of content to upload (puppet or yum, required)")
        )
        parser.add_option(
            "--chunk", dest="chunk", help=_("number of bytes to send to server at a time (default is 1048575)")
        )

        opt_parser_add_org(parser, required=1)
        opt_parser_add_environment(parser, default="Library")
        opt_parser_add_product(parser)

    def check_options(self, validator):
        validator.require(("filepath", "content_type"))
        if not validator.exists("repo_id"):
            validator.require(("repo", "org"))
            validator.require_at_least_one_of(("product", "product_label", "product_id"))
            validator.mutually_exclude("product", "product_label", "product_id")

    def run(self):
        repo_id = self.get_option("repo_id")
        repo_name = self.get_option("repo")
        org_name = self.get_option("org")
        env_name = self.get_option("environment")
        prod_name = self.get_option("product")
        prod_label = self.get_option("product_label")
        prod_id = self.get_option("product_id")
        filepath = self.get_option("filepath")
        content_type = self.get_option("content_type")
        chunk = self.get_option("chunk")

        if not repo_id:
            repo = get_repo(org_name, repo_name, prod_name, prod_label, prod_id, env_name, False)
            repo_id = repo["id"]

        if not self._valid_upload_type(repo_id, content_type):
            return os.EX_DATAERR

        paths = []
        if os.path.isdir(filepath):
            for dirname, __, filenames in os.walk(filepath):
                paths = [os.path.join(dirname, filename) for filename in filenames]
        elif os.path.isfile(filepath):
            paths = [filepath]
        else:
            print _("Invalid path '%s'.") % filepath
            return os.EX_DATAERR

        uploads = []
        for path in paths:
            try:
                upload = self.send_file(path, repo_id, content_type, chunk)
                uploads.append(upload)
            except FileUploadError:
                if len(paths) > 1:
                    print _("Skipping file '%s'.") % path

        if uploads:
            run_spinner_in_bg(
                self.upload_api.import_into_repo, [repo_id, uploads], message=_("Importing content into repository")
            )

            self.remove_uploads(repo_id, uploads)

            print _("Successfully imported content into repository.")
            return os.EX_OK
        else:
            return os.EX_DATAERR

    def _valid_upload_type(self, repo_id, content_type):
        if content_type not in self.CONTENT_TYPES:
            print _("Content type '%(type)s' not valid. Must be one of: %(types)s.") % {
                "type": content_type,
                "types": (", ").join(self.CONTENT_TYPES),
            }
            return False

        repo = self.api.repo(repo_id)
        if repo["content_type"] != content_type:
            print _("Repo [ %(repo)s ] does not accept %(type)s uploads.") % {
                "repo": repo["name"],
                "type": content_type,
            }
            return False
        return True

    def remove_uploads(self, repo_id, uploads):
        for upload in uploads:
            self.upload_api.delete(repo_id, upload["id"])

    def send_file(self, filepath, repo_id, content_type, chunk):
        filename = os.path.basename(filepath)
        unit_key, metadata = ContentUpload.get_content_data(content_type, filepath)

        if unit_key is None and metadata is None:
            raise FileUploadError

        try:
            upload_id = self.upload_api.create(repo_id)["upload_id"]
            run_spinner_in_bg(
                self.send_content,
                [repo_id, upload_id, filepath, chunk],
                message=_("Uploading '%s' to server... ") % filename,
            )
        finally:
            print _("Successfully uploaded '%s' into repository") % filename

        return {"id": upload_id, "unit_key": unit_key, "metadata": metadata}

    def send_content(self, repo_id, upload_id, filepath, chunk=None):
        if not chunk:
            chunk = 1048575  # see SSLRenegBufferSize in apache

        with open(filepath, "rb") as f:
            offset = 0
            while True:
                piece = f.read(chunk)

                if piece == "":
                    break  # end of file

                self.upload_api.upload_bits(repo_id, upload_id, offset, piece)
                offset += chunk
Beispiel #2
0
class ContentUpload(SingleRepoAction):

    def __init__(self):
        super(ContentUpload, self).__init__()
        self.upload_api = ContentUploadAPI()

    description = _('upload content into a repository')

    @classmethod
    def get_content_data(cls, content_type, filepath):
        unit_key = metadata = None
        if content_type == "yum":
            try:
                unit_key, metadata = generate_rpm_data(filepath)
            except InvalidRPMError:
                print _("Invalid rpm '%s'. Please check the file and try again.") % filepath
        elif content_type == "puppet":
            try:
                unit_key, metadata = generate_puppet_data(filepath)
            except ExtractionException:
                print _("Invalid puppet module '%s'. Please check the file and try again.") % filepath
        else:
            print _("Content type '%s' not valid. Must be puppet or yum.") % content_type

        return unit_key, metadata

    def setup_parser(self, parser):
        parser.add_option('--repo_id', dest='repo_id', help=_("repository ID (required)"))
        parser.add_option('--repo', dest='repo', help=_("repository name"))
        parser.add_option('--filepath', dest='filepath',
                          help=_("path of file or directory of files to upload (required)"))
        parser.add_option('--content_type', dest='content_type',
                          help=_("type of content to upload (puppet or yum, required)"))
        parser.add_option('--chunk', dest='chunk',
                          help=_("number of bytes to send to server at a time (default is 1048575)"))

        opt_parser_add_org(parser, required=1)
        opt_parser_add_environment(parser, default="Library")
        opt_parser_add_product(parser)

    def check_options(self, validator):
        validator.require(('filepath', 'content_type'))
        if not validator.exists('repo_id'):
            validator.require(('repo', 'org'))
            validator.require_at_least_one_of(('product', 'product_label', 'product_id'))
            validator.mutually_exclude('product', 'product_label', 'product_id')

    def run(self):
        repo_id = self.get_option('repo_id')
        repo_name = self.get_option('repo')
        org_name = self.get_option('org')
        env_name = self.get_option('environment')
        prod_name = self.get_option('product')
        prod_label = self.get_option('product_label')
        prod_id = self.get_option('product_id')
        filepath = self.get_option("filepath")
        content_type = self.get_option("content_type")
        chunk = self.get_option("chunk")

        if not repo_id:
            repo = get_repo(org_name, repo_name, prod_name, prod_label, prod_id, env_name, False)
            repo_id = repo["id"]

        paths = []
        if os.path.isdir(filepath):
            for dirname, __, filenames in os.walk(filepath):
                paths = [os.path.join(dirname, filename) for filename in filenames]
        elif os.path.isfile(filepath):
            paths = [filepath]
        else:
            print _("Invalid path '%s'.") % filepath
            return os.EX_DATAERR

        for path in paths:
            try:
                self.send_file(path, repo_id, content_type, chunk)
            except FileUploadError:
                if len(paths) > 1:
                    print _("Skipping file '%s'.") % path

        return os.EX_OK

    def send_file(self, filepath, repo_id, content_type, chunk):
        filename = os.path.basename(filepath)
        unit_key, metadata = ContentUpload.get_content_data(content_type, filepath)

        if unit_key is None and metadata is None:
            raise FileUploadError

        upload_id = self.upload_api.create(repo_id)["upload_id"]
        self.send_content(repo_id, upload_id, filepath, chunk)
        run_spinner_in_bg(self.upload_api.import_into_repo,
                          [repo_id, upload_id, unit_key, metadata],
                          message=_("Uploading '%s' to server, please... ") % filename)
        self.upload_api.delete(repo_id, upload_id)

        print _("Successfully uploaded '%s' into repository") % filename

    def send_content(self, repo_id, upload_id, filepath, chunk=None):
        if not chunk:
            chunk = 1048575  # see SSLRenegBufferSize in apache

        with open(filepath, "rb") as f:
            offset = 0
            while True:
                piece = f.read(chunk)

                if piece == "":
                    break  # end of file

                self.upload_api.upload_bits(repo_id, upload_id, offset, piece)
                offset += chunk