def get_cluster_config(self, data):
        """Get the configuration of the cluster with the given name in PKS.

        System administrator gets the given cluster config regardless of
        who is the owner of the cluster. Other users get config only on
        the cluster they own.

        :return: Configuration of the cluster.

        :rtype: str
        """
        cluster_name = data[RequestKey.CLUSTER_NAME]

        if self.tenant_client.is_sysadmin() or \
                is_org_admin(self.client_session):
            cluster_info = self.get_cluster_info(data)
            qualified_cluster_name = cluster_info['pks_cluster_name']
        else:
            qualified_cluster_name = self._append_user_id(cluster_name)

        self._check_cluster_isolation(cluster_name, qualified_cluster_name)

        cluster_api = ClusterApiV1(api_client=self.client_v1)

        LOGGER.debug(f"Sending request to PKS: {self.pks_host_uri} to get"
                     f" detailed configuration of cluster with name: "
                     f"{cluster_name}")
        config = cluster_api.create_user(cluster_name=qualified_cluster_name)
        LOGGER.debug(f"Received response from PKS: {self.pks_host_uri} on "
                     f"cluster: {cluster_name} with details: {config}")
        cluster_config = yaml.safe_dump(config, default_flow_style=False)

        return self.filter_traces_of_user_context(cluster_config)
    def resize_cluster(self, **cluster_spec):
        """Resize the cluster of a given name to given number of worker nodes.

        System administrator can resize the given cluster regardless of
        who is the owner of the cluster. Other users can only resize
        the cluster they own.

        :param dict cluster_spec: named parameters that are required to
        resize cluster (cluster_name, node_count)

        :return: response status

        :rtype: dict

        """
        cluster_name = cluster_spec['cluster_name']

        if self.tenant_client.is_sysadmin() \
                or is_org_admin(self.client_session):
            cluster_info = self.get_cluster_info(cluster_name)
            qualified_cluster_name = cluster_info['pks_cluster_name']
        else:
            qualified_cluster_name = self._append_user_id(cluster_name)

        self._check_cluster_isolation(cluster_name, qualified_cluster_name)

        cluster_spec['cluster_name'] = qualified_cluster_name
        result = self._resize_cluster(**cluster_spec)
        self._restore_original_name(result)
        self._filter_pks_properties(result)
        return result
    def delete_cluster(self, cluster_name):
        """Delete the cluster with a given name in PKS environment.

        System administrator can delete the given cluster regardless of
        who is the owner of the cluster. Other users can only delete
        the cluster they own.

        :param str cluster_name: Name of the cluster
        """
        if self.tenant_client.is_sysadmin() \
                or is_org_admin(self.client_session):
            cluster_info = self.get_cluster_info(cluster_name)
            qualified_cluster_name = cluster_info['pks_cluster_name']
        else:
            qualified_cluster_name = self._append_user_id(cluster_name)

        result = self._delete_cluster(qualified_cluster_name)

        # remove cluster network isolation
        LOGGER.debug(f"Removing network isolation of cluster {cluster_name}.")
        try:
            cluster_network_isolater = ClusterNetworkIsolater(self.nsxt_client)
            cluster_network_isolater.remove_cluster_isolation(
                qualified_cluster_name)
        except Exception as err:
            # NSX-T oprations are idempotent so they should not cause erros
            # if say NSGroup is missing. But for any other exception, simply
            # catch them and ignore.
            LOGGER.debug(f"Error {err} occured while deleting cluster "
                         f"isolation rules for cluster {cluster_name}")

        self._restore_original_name(result)
        self._filter_pks_properties(result)
        return result
예제 #4
0
    def delete_cluster(self, data):
        """Delete the cluster with a given name in PKS environment.

        System administrator can delete the given cluster regardless of
        who is the owner of the cluster. Other users can only delete
        the cluster they own.

        :param str cluster_name: Name of the cluster
        """
        cluster_name = data[RequestKey.CLUSTER_NAME]

        if self.tenant_client.is_sysadmin() \
                or is_org_admin(self.client_session):
            cluster_info = self._get_cluster_info(data)
            qualified_cluster_name = cluster_info['pks_cluster_name']
        else:
            qualified_cluster_name = self._append_user_id(cluster_name)

        result = {}
        cluster_api = ClusterApi(api_client=self.client)

        try:
            LOGGER.debug(
                f"Sending request to PKS: {self.pks_host_uri} to delete "
                f"the cluster with name: {qualified_cluster_name}")
            cluster_api.delete_cluster(cluster_name=qualified_cluster_name)

            LOGGER.debug(
                f"PKS: {self.pks_host_uri} accepted the request to delete"
                f" the cluster: {qualified_cluster_name}")
        except ApiException as err:
            LOGGER.debug(f"Deleting cluster {qualified_cluster_name} failed"
                         f" with error:\n {err}")
            raise PksServerError(err.status, err.body)

        result['name'] = qualified_cluster_name
        result['task_status'] = 'in progress'

        # remove cluster network isolation
        LOGGER.debug("Removing network isolation of cluster "
                     f"{qualified_cluster_name}.")
        try:
            cluster_network_isolater = ClusterNetworkIsolater(self.nsxt_client)
            cluster_network_isolater.remove_cluster_isolation(
                qualified_cluster_name)
        except Exception as err:
            # NSX-T oprations are idempotent so they should not cause erros
            # if say NSGroup is missing. But for any other exception, simply
            # catch them and ignore.
            LOGGER.debug(f"Error {err} occured while deleting cluster "
                         "isolation rules for cluster "
                         f"{qualified_cluster_name}")

        return result
    def _filter_clusters(self, cluster_list, **kwargs):
        """Filter the cluster list based on vdc, org by personae.

        Apply the filters in the following order of priority and return the
        result once the specific-persona-only filter is applied.

        1. Filter clusters based on vdc for all personae.
        2. Filter clusters based on org only for sysadmin.
        3. Filter clusters for org admin based on visibility.
        4. Filter clusters for tenant users based on ownership only.

        :param list cluster_list: list of clusters
        :return: filtered list of clusters

        :rtype: list
        TODO() These filters should be moved to either broker layer or
        delegated to dedicated filter class say: PksClusterFilter.
        """
        # Apply vdc filter, if provided to all personae.
        if kwargs.get(RequestKey.OVDC_NAME):
            cluster_list = \
                self._apply_vdc_filter(cluster_list,
                                       kwargs.get(RequestKey.OVDC_NAME))

        # Apply org filter, if provided, for sys admin.
        if self.tenant_client.is_sysadmin():
            org_name = kwargs.get(RequestKey.ORG_NAME)
            if org_name and org_name.lower() != SYSTEM_ORG_NAME.lower():
                cluster_list = self._apply_org_filter(cluster_list, org_name)
            return cluster_list

        # Filter the cluster list for org admin and others.
        if is_org_admin(self.client_session) or kwargs.get(
                'is_org_admin_search'):  # noqa: E501
            # TODO() - Service accounts for exclusive org does not
            #  require the following filtering.
            cluster_list = [
                cluster_dict for cluster_dict in cluster_list
                if self._is_cluster_visible_to_org_admin(cluster_dict)
            ]
        else:
            cluster_list = [
                cluster_dict for cluster_dict in cluster_list
                if self._is_user_cluster_owner(cluster_dict)
            ]

            # 'is_admin_request' is a flag that is used to restrict access to
            # user context and other secured information on pks cluster
            # information.
            if not kwargs.get('is_admin_request'):
                for cluster in cluster_list:
                    self._filter_pks_properties(cluster)
        return cluster_list
예제 #6
0
    def resize_cluster(self, data):
        """Resize the cluster of a given name to given number of worker nodes.

        System administrator can resize the given cluster regardless of
        who is the owner of the cluster. Other users can only resize
        the cluster they own.


        :return: response status

        :rtype: dict

        """
        cluster_name = data[RequestKey.CLUSTER_NAME]
        num_workers = data[RequestKey.NUM_WORKERS]

        if self.tenant_client.is_sysadmin() \
                or is_org_admin(self.client_session):
            cluster_info = self._get_cluster_info(data)
            qualified_cluster_name = cluster_info['pks_cluster_name']
        else:
            qualified_cluster_name = self._append_user_id(cluster_name)

        self._check_cluster_isolation(cluster_name, qualified_cluster_name)

        result = {}
        cluster_api = ClusterApi(api_client=self.client)
        LOGGER.debug(f"Sending request to PKS:{self.pks_host_uri} to resize "
                     f"the cluster with name: {qualified_cluster_name} to "
                     f"{num_workers} worker nodes")
        resize_params = \
            UpdateClusterParameters(kubernetes_worker_instances=num_workers)
        try:
            cluster_api.update_cluster(qualified_cluster_name,
                                       body=resize_params)
        except ApiException as err:
            LOGGER.debug(f"Resizing cluster {qualified_cluster_name} failed"
                         f" with error:\n {err}")
            raise PksServerError(err.status, err.body)
        LOGGER.debug(f"PKS: {self.pks_host_uri} accepted the request to resize"
                     f" the cluster: {qualified_cluster_name}")

        result['name'] = qualified_cluster_name
        result['task_status'] = 'in progress'
        self._restore_original_name(result)
        if not self.tenant_client.is_sysadmin():
            self._filter_sensitive_pks_properties(result)
        return result
예제 #7
0
    def _get_cluster_info(self, data):
        """Get the details of a cluster with a given name in PKS environment.

        System administrator gets the given cluster information regardless of
        who is the owner of the cluster. Other users get info only on
        the cluster they own.

        :param str cluster_name: Name of the cluster
        :return: Details of the cluster.

        :rtype: dict
        """
        cluster_name = data[RequestKey.CLUSTER_NAME]
        # The structure of info returned by list_cluster and get_cluster is
        # identical, hence using list_cluster and filtering by name in memory
        # to retrieve info of the requested cluster.
        cluster_info_list = self._list_clusters(data)
        result = {}
        if self.tenant_client.is_sysadmin() \
                or is_org_admin(self.client_session) \
                or data.get('is_org_admin_search'):
            filtered_cluster_info_list = []
            for cluster_info in cluster_info_list:
                if cluster_info['name'] == cluster_name:
                    filtered_cluster_info_list.append(cluster_info)
            LOGGER.debug(
                f"Filtered list of clusters:{filtered_cluster_info_list}")
            if len(filtered_cluster_info_list) > 1:
                raise PksDuplicateClusterError(
                    requests.codes.bad_request,
                    f"Multiple clusters with name '{cluster_name}' exists.")
            if len(filtered_cluster_info_list) == 0:
                raise PksServerError(requests.codes.not_found,
                                     f"cluster {cluster_name} not found.")
            result = filtered_cluster_info_list[0]
        else:
            qualified_cluster_name = self._append_user_id(cluster_name)
            for cluster_info in cluster_info_list:
                if cluster_info['pks_cluster_name'] == qualified_cluster_name:
                    result = cluster_info
                    break
            if not result:
                raise PksServerError(requests.codes.not_found,
                                     f"cluster {cluster_name} not found.")

        return result
    def list_clusters(self, **kwargs):
        """Get list of clusters in PKS environment.

        System administrator gets all the clusters for the given service
        account. Other users get only those clusters which they own.

        :return: a list of cluster-dictionaries

        :rtype: list
        """
        cluster_list = self._list_clusters()

        # Required for all personae
        for cluster in cluster_list:
            self._restore_original_name(cluster)

        # Complete list of clusters for sysadmin
        if self.tenant_client.is_sysadmin():
            return cluster_list

        # Filter the list for org admin and others.
        if is_org_admin(self.client_session) or \
                kwargs.get('is_org_admin_search'):
            # TODO() - Service accounts for exclusive org does not
            #  require the following filtering.
            cluster_list = [
                cluster_dict for cluster_dict in cluster_list
                if self._is_cluster_visible_to_org_admin(cluster_dict)
            ]
        else:
            cluster_list = [
                cluster_dict for cluster_dict in cluster_list
                if self._is_user_cluster_owner(cluster_dict)
            ]

            # 'is_admin_request' is a flag that is used to restrict access to
            # user context and other secured information on pks cluster
            # information.
            if not kwargs.get('is_admin_request'):
                for cluster in cluster_list:
                    self._filter_pks_properties(cluster)
        return cluster_list
    def get_cluster_config(self, cluster_name):
        """Get the configuration of the cluster with the given name in PKS.

        System administrator gets the given cluster config regardless of
        who is the owner of the cluster. Other users get config only on
        the cluster they own.

        :param str cluster_name: Name of the cluster
        :return: Configuration of the cluster.

        :rtype: str
        """
        if self.tenant_client.is_sysadmin() or \
                is_org_admin(self.client_session):
            cluster_info = self.get_cluster_info(cluster_name)
            qualified_cluster_name = cluster_info['pks_cluster_name']
        else:
            qualified_cluster_name = self._append_user_id(cluster_name)

        self._check_cluster_isolation(cluster_name, qualified_cluster_name)

        config_info = self._get_cluster_config(qualified_cluster_name)
        return self.filter_traces_of_user_context(config_info)
    def get_cluster_info(self, data):
        """Get the details of a cluster with a given name in PKS environment.

        System administrator gets the given cluster information regardless of
        who is the owner of the cluster. Other users get info only on
        the cluster they own.

        :param str cluster_name: Name of the cluster
        :return: Details of the cluster.

        :rtype: dict
        """
        cluster_name = data[RequestKey.CLUSTER_NAME]

        if self.tenant_client.is_sysadmin() \
                or is_org_admin(self.client_session) \
                or data.get('is_org_admin_search'):
            cluster_list = self.list_clusters(data)
            filtered_cluster_list = \
                self._filter_list_by_cluster_name(cluster_list, cluster_name)
            LOGGER.debug(f"filtered Cluster List:{filtered_cluster_list}")
            if len(filtered_cluster_list) > 1:
                raise PksDuplicateClusterError(
                    requests.codes.bad_request,
                    f"Multiple clusters with name '{cluster_name}' exists.")
            if len(filtered_cluster_list) == 0:
                raise PksServerError(requests.codes.not_found,
                                     f"cluster {cluster_name} not found.")
            return filtered_cluster_list[0]

        cluster_info = \
            self._get_cluster_info(self._append_user_id(cluster_name))
        self._restore_original_name(cluster_info)
        if not data.get('is_admin_request'):
            self._filter_pks_properties(cluster_info)

        return cluster_info
    def get_cluster_info(self, cluster_name, **kwargs):
        """Get the details of a cluster with a given name in PKS environment.

        System administrator gets the given cluster information regardless of
        who is the owner of the cluster. Other users get info only on
        the cluster they own.

        :param str cluster_name: Name of the cluster
        :return: Details of the cluster.

        :rtype: dict
        """
        if self.tenant_client.is_sysadmin() \
                or is_org_admin(self.client_session) \
                or kwargs.get('is_org_admin_search'):
            cluster_list = self.list_clusters(
                is_org_admin_search=kwargs.get('is_org_admin_search'))
            filtered_cluster_list = \
                self._filter_list_by_cluster_name(cluster_list, cluster_name)
            LOGGER.debug(f"filtered Cluster List:{filtered_cluster_list}")
            # TODO() Sys admin may encounter multiple clusters with the same
            #  name; in that case choosing the first one could be wrong.
            #  Needs revisit
            if len(filtered_cluster_list) > 0:
                cluster_info = filtered_cluster_list[0]
            else:
                raise PksServerError(HTTPStatus.NOT_FOUND,
                                     f"cluster {cluster_name} not found")
        else:
            cluster_info = \
                self._get_cluster_info(self._append_user_id(cluster_name))
            self._restore_original_name(cluster_info)
            if not kwargs.get('is_admin_request'):
                self._filter_pks_properties(cluster_info)

        return cluster_info