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
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