Example #1
0
    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()
Example #2
0
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)
Example #3
0
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)
Example #4
0
    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()
Example #5
0
    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.')
Example #6
0
    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.')
Example #7
0
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)
Example #8
0
    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))
Example #9
0
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")