def share_catalog(cls): """Shares the test catalog with all members in the test organization. :raises: Exception: if the class variable _org_href is not populated. :raises: EntityNotFoundException: if the catalog in question is missing. """ cls._basic_check() if cls._org_href is None: raise Exception('Org ' + cls._config['vcd']['default_org_name'] + ' doesn\'t exist.') try: catalog_author_client = Environment.get_client_in_default_org( CommonRoles.CATALOG_AUTHOR) org = Org(catalog_author_client, href=cls._org_href) catalog_name = cls._config['vcd']['default_catalog_name'] catalog_records = org.list_catalogs() for catalog_record in catalog_records: if catalog_record.get('name') == catalog_name: cls._logger.debug('Sharing catalog ' + catalog_name + ' to' ' all members of org ' + org.get_name()) org.share_catalog_with_org_members( catalog_name=catalog_name) return raise EntityNotFoundException('Catalog ' + catalog_name + 'doesn\'t exist.') finally: catalog_author_client.logout()
def list_catalogs_or_items(ctx, catalog_name): try: restore_session(ctx) client = ctx.obj['client'] if catalog_name is None: in_use_org_href = ctx.obj['profiles'].get('org_href') org = Org(client, in_use_org_href) result = org.list_catalogs() else: result = [] if is_sysadmin(ctx): resource_type = ResourceType.ADMIN_CATALOG_ITEM.value else: resource_type = ResourceType.CATALOG_ITEM.value q = client.get_typed_query( resource_type, query_result_format=QueryResultFormat.ID_RECORDS, equality_filter=('catalogName', catalog_name)) records = list(q.execute()) if len(records) == 0: result = 'not found' else: for r in records: result.append(to_dict(r, resource_type=resource_type)) stdout(result, ctx) except Exception as e: stderr(e, ctx)
def list_catalogs_or_items(ctx, catalog_name): try: client = ctx.obj['client'] if catalog_name is None: org_name = ctx.obj['profiles'].get('org') in_use_org_href = ctx.obj['profiles'].get('org_href') org = Org(client, in_use_org_href, org_name == 'System') result = org.list_catalogs() else: result = [] resource_type = \ 'adminCatalogItem' if is_admin(ctx) else 'catalogItem' q = client.get_typed_query(resource_type, query_result_format=QueryResultFormat. ID_RECORDS, qfilter='catalogName==%s' % catalog_name) records = list(q.execute()) if len(records) == 0: result = 'not found' else: for r in records: result.append(to_dict(r, resource_type=resource_type)) stdout(result, ctx) except Exception as e: stderr(e, ctx)
def create_catalog(cls): """Creates a catalog by the name specified in the configuration file. Skips creating one, if such a catalog already exists. :raises: Exception: if the class variable _org_href is not populated. """ cls._basic_check() if cls._org_href is None: raise Exception('Org ' + cls._config['vcd']['default_org_name'] + ' doesn\'t exist.') try: catalog_author_client = Environment.get_client_in_default_org( CommonRoles.CATALOG_AUTHOR) org = Org(catalog_author_client, href=cls._org_href) catalog_name = cls._config['vcd']['default_catalog_name'] catalog_records = org.list_catalogs() for catalog_record in catalog_records: if catalog_record.get('name') == catalog_name: cls._logger.debug('Reusing existing catalog ' + catalog_name) return cls._logger.debug('Creating new catalog ' + catalog_name) catalog_resource = org.create_catalog( name=catalog_name, description='') catalog_author_client.get_task_monitor().wait_for_success( task=catalog_resource.Tasks.Task[0]) finally: catalog_author_client.logout()
def share_catalog(cls): """Shares the test catalog with all members in the test org. :return: Nothing :raises: Exception: If the class variable _org_href is not populated or the catalog in question is missing. """ cls._basic_check() if cls._org_href is None: raise Exception('Org ' + cls._config['vcd']['default_org_name'] + ' doesn\'t exist.') org = Org(cls._sys_admin_client, href=cls._org_href) catalog_name = cls._config['vcd']['default_catalog_name'] catalog_records = org.list_catalogs() for catalog_record in catalog_records: if catalog_record.get('name').lower() == catalog_name.lower(): print('Sharing catalog ' + catalog_name) # TODO : This method is buggy, share_catalog shares with only # org-admins of other orgs - see VCDA-603 org.share_catalog(name=catalog_name) return raise Exception('Catalog ' + catalog_name + 'doesn\'t exists.')
def share_catalog(cls): """Shares the test catalog with all members in the test organization. :return: Nothing :raises: Exception: if the class variable _org_href is not populated. :raises: EntityNotFoundException: if the catalog in question is missing. """ cls._basic_check() if cls._org_href is None: raise Exception('Org ' + cls._config['vcd']['default_org_name'] + ' doesn\'t exist.') org = Org(cls._sys_admin_client, href=cls._org_href) catalog_name = cls._config['vcd']['default_catalog_name'] catalog_records = org.list_catalogs() for catalog_record in catalog_records: if catalog_record.get('name').lower() == catalog_name.lower(): cls._logger.debug('Sharing catalog ' + catalog_name + ' to all members of org ' + org.get_name()) org.share_catalog_with_org_members(catalog_name=catalog_name) return raise EntityNotFoundException('Catalog ' + catalog_name + 'doesn\'t' 'exists.')
def get_catalog_id_from_path(self, catalog_name=None, path=None, progress=False): """ Args catalog - catalog name to be created path: - valid path to OVF file. progress - boolean progress bar show progress bar. Return: if image uploaded correct method will provide image catalog UUID. """ if not path: raise Exception("Image path can't be None.") if not os.path.isfile(path): raise Exception("Can't read file. File not found.") if not os.access(path, os.R_OK): raise Exception("Can't read file. Check file permission to read.") self.logger.debug("get_catalog_id_from_path() client requesting {} ".format(path)) _, filename = os.path.split(path) _, file_extension = os.path.splitext(path) if file_extension != '.ovf': self.logger.debug("Wrong file extension {} connector support only OVF container.".format(file_extension)) raise Exception("Wrong container. vCloud director supports only OVF.") self.logger.debug("File name {} Catalog Name {} file path {} ".format(filename, catalog_name, path)) try: client = self.connect() if not client: raise Exception("Failed to connect vCD") org = Org(client, resource=client.get_org()) catalogs = org.list_catalogs() except Exception as exp: self.logger.debug("Failed get catalogs() with Exception {} ".format(exp)) raise Exception("Failed get catalogs() with Exception {} ".format(exp)) if len(catalogs) == 0: self.logger.info("Creating a new catalog entry {} in vcloud director".format(catalog_name)) result = org.create_catalog(catalog_name, catalog_name) if result is None: raise Exception("Failed to create new catalog {} ".format(catalog_name)) result = self.upload_ovf(org=org, catalog_name=catalog_name, image_name=filename.split(".")[0], media_file_name=path, description='medial_file_name', progress=progress) if not result: raise Exception("Failed to create vApp template for catalog {} ".format(catalog_name)) return self.get_catalogid(catalog_name, catalogs) else: for catalog in catalogs: # search for existing catalog if we find same name we return ID if catalog['name'] == catalog_name: self.logger.debug("Found existing catalog entry for {} " "catalog id {}".format(catalog_name, self.get_catalogid(catalog_name, catalogs))) return self.get_catalogid(catalog_name, catalogs) # if we didn't find existing catalog we create a new one and upload image. self.logger.debug("Creating new catalog entry {} - {}".format(catalog_name, catalog_name)) result = org.create_catalog(catalog_name, catalog_name) if result is None: raise Exception("Failed to create new catalog {} ".format(catalog_name)) result = self.upload_ovf(org=org, catalog_name=catalog_name, image_name=filename.split(".")[0], media_file_name=path, description='medial_file_name', progress=progress) if not result: raise Exception("Failed create vApp template for catalog {} ".format(catalog_name))
class OVFUploader(object): """ Class to convert input image into OVF format """ def __init__(self, ovf_file, vcd_url=None, username=None, password=None, orgname=None): self.ovf_file = os.path.abspath(ovf_file) self.vcd_url = vcd_url self.username = username self.password = password self.orgname = orgname try: client = Client(self.vcd_url, verify_ssl_certs=False, api_version=ApiVersion.VERSION_32.value, log_requests=True, log_headers=True, log_bodies=True, log_file=LOG_FILE) # sclient.set_highest_supported_version() client.set_credentials( BasicLoginCredentials(self.username, self.orgname, self.password)) logger.info("Logged into {} using version {}".format( self.vcd_url, client.get_api_version())) self.client = client self.org = Org(self.client, resource=self.client.get_org()) except Exception as exp: problem = Exception( "Failed to connect to vCD at {}, org {}, username {}:\n{}". format(self.vcd_url, self.orgname, self.username, exp)) logger.error(problem) raise problem try: # Retrieve the VM name from the OVF. We will use this as both the image and catalog name OVF_tree = etree.parse(self.ovf_file) root = OVF_tree.getroot() nsmap = {k: v for k, v in root.nsmap.items() if k} nsmap["xmlns"] = "http://schemas.dmtf.org/ovf/envelope/1" virtuasystem = root.find('xmlns:VirtualSystem', nsmap) name_tag = virtuasystem.find('xmlns:Name', nsmap) self.image_name = name_tag.text info_tag = virtuasystem.find('xmlns:Info', nsmap) self.image_description = info_tag.text references = root.find('xmlns:References', nsmap) file = references.find('xmlns:File', nsmap) self.vmdk_file = "{}/{}".format( os.path.dirname(self.ovf_file), file.attrib['{http://schemas.dmtf.org/ovf/envelope/1}href']) logger.info("Loaded VM {}: {}".format(self.image_name, self.image_description)) except Exception as exp: problem = Exception( "Failed to fetch VirtualSystem Name element from OVF {}:\n{}". format(self.ovf_file, exp)) logger.error(problem) raise problem def make_catalog(self): self.catalog_id = None try: for catalog in self.org.list_catalogs(): if catalog['name'] == self.image_name: self.catalog_id = catalog['id'] if self.catalog_id is None: logger.info("Creating a new catalog entry {} in vCD".format( self.image_name)) result = self.org.create_catalog(self.image_name, self.image_description) if result is None: raise Exception("Failed to create new catalog entry") self.catalog_id = result.attrib['id'].split(':')[-1] self.org.reload() logger.debug("Using catalog {}, id {}".format( self.image_name, self.catalog_id)) except Exception as exp: problem = Exception("Failed to fetch catalog for {}:\n{} ".format( self.image_name, exp)) logger.error(problem) raise problem def upload_ovf(self): ova_tarfilename, _ = os.path.splitext(self.ovf_file) ova_tarfilename += '.ova' try: # Check if the content already exists: resource_type = ResourceType.CATALOG_ITEM.value q = self.client.get_typed_query( resource_type, query_result_format=QueryResultFormat.ID_RECORDS, equality_filter=('catalogName', self.image_name)) for item in list(q.execute()): if item.get('name') == self.image_name: logger.info("Removing old version from catalog") try: self.org.delete_catalog_item(self.image_name, self.image_name) except InternalServerException as exp: problem = Exception( "Cannot delete vAppTemplate {}. Please check in vCD if " "the content is still being imported into the catalog" .format(self.image_name)) raise problem # Create a single OVA bundle ova = tarfile.open(name=ova_tarfilename, mode='w') ova.add(self.ovf_file, arcname=os.path.basename(self.ovf_file)) ova.add(self.vmdk_file, arcname=os.path.basename(self.vmdk_file)) ova.close() logger.info("Uploading content to vCD") self.org.upload_ovf(self.image_name, ova_tarfilename, item_name=self.image_name, description=self.image_description, callback=report_progress) except Exception as exp: problem = Exception("Failed to upload OVF {}:\n{} ".format( self.ovf_file, exp)) logger.error(problem) raise problem finally: if os.path.exists(ova_tarfilename): os.remove(ova_tarfilename) def wait_for_task_completion(self): logger.info("Importing content to vCD") try: query = self.client.get_typed_query( query_type_name=ResourceType.TASK.value, qfilter='ownerName==' + self.username + ';(status==queued,status==preRunning,status==running)', query_result_format=QueryResultFormat.REFERENCES) upload_task = None tasks = list(query.execute()) for task in tasks: if task.get('name') == 'VDC_UPLOAD_OVF_CONTENTS': upload_task = self.client.get_resource(task.get('href')) break bad_statuses = [ TaskStatus.ABORTED, TaskStatus.CANCELED, TaskStatus.ERROR ] except Exception as exp: problem = Exception("Failed to import OVF {}:\n{} ".format( self.ovf_file, exp)) logger.error(problem) raise problem while (True): task_status = upload_task.get('status').lower() if (hasattr(upload_task, 'Progress')): print("{}% complete \r".format(upload_task.Progress), end='') for status in bad_statuses: if task_status == status.value.lower(): problem = Exception( "vCD failed to import OVF {}:\n{}: {} ".format( self.ovf_file, task_status, upload_task.Error.get('Message'))) logger.error(problem) raise problem if task_status == str(TaskStatus.SUCCESS.value).lower(): break time.sleep(2) upload_task = self.client.get_resource(upload_task.get('href')) logger.info("OVF upload and import complete, content is ready to use")