def list_clusters(self): """Get list of clusters ((TODO)for a given vCD user) in PKS environment. :return: a list of cluster-dictionaries :rtype: list """ result = {} result['body'] = [] result['status_code'] = OK cluster_api = ClusterApi(api_client=self.pks_client) LOGGER.debug(f'Sending request to PKS: {self.host} ' f'to list all clusters') clusters = cluster_api.list_clusters() list_of_cluster_dicts = [] for cluster in clusters: cluster_dict = { 'name': cluster.name, 'plan-name': cluster.plan_name, 'uuid': cluster.uuid, 'status': cluster.last_action_state, 'last-action': cluster.last_action, 'k8_master_ips': cluster.kubernetes_master_ips } list_of_cluster_dicts.append(cluster_dict) LOGGER.debug(f'Received response from PKS: {self.host} on the list of ' f'clusters: {list_of_cluster_dicts}') result['body'] = list_of_cluster_dicts return result
def _get_cluster_info(self, cluster_name): """Get the details of a cluster with a given name in PKS environment. :param str cluster_name: Name of the cluster :return: Details of the cluster. :rtype: dict """ cluster_api = ClusterApi(api_client=self.pks_client) LOGGER.debug(f"Sending request to PKS: {self.pks_host_uri} to get " f"details of cluster with name: {cluster_name}") try: cluster = cluster_api.get_cluster(cluster_name=cluster_name) except ApiException as err: LOGGER.debug(f"Getting cluster info on {cluster_name} failed with " f"error:\n {err}") raise PksServerError(err.status, err.body) cluster_dict = cluster.to_dict() cluster_params_dict = cluster_dict.pop('parameters') cluster_dict.update(cluster_params_dict) LOGGER.debug(f"Received response from PKS: {self.pks_host_uri} on " f"cluster: {cluster_name} with details: {cluster_dict}") return cluster_dict
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 = ClusterApi(api_client=self.client) LOGGER.debug(f"Sending request to PKS: {self.pks_host_uri} to get" f" kubectl configuration of cluster with name: " f"{qualified_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: {qualified_cluster_name} with details: " f"{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_name, node_count, **kwargs): """Resize the cluster of a given name to given number of worker nodes. :param str cluster_name: Name of the cluster :param int node_count: New size of the worker nodes """ result = {} cluster_api = ClusterApi(api_client=self.pks_client) LOGGER.debug(f"Sending request to PKS:{self.pks_host_uri} to resize " f"the cluster with name: {cluster_name} to " f"{node_count} worker nodes") resize_params = UpdateClusterParameters( kubernetes_worker_instances=node_count) try: cluster_api.update_cluster(cluster_name, body=resize_params) except ApiException as err: LOGGER.debug(f"Resizing cluster {cluster_name} failed with " f"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: {cluster_name}") result['cluster_name'] = cluster_name result['task_status'] = 'in progress' return result
def resize_cluster(self, name, num_worker_nodes): """Resize the cluster of a given name to given number of worker nodes. :param str name: Name of the cluster :param int num_worker_nodes: New size of the worker nodes (should be greater than the current number). :return: None """ result = {} result['body'] = [] cluster_api = ClusterApi(api_client=self.pks_client) LOGGER.debug(f'Sending request to PKS:{self.host} to resize the ' f'cluster with name: {name} to ' f'{num_worker_nodes} worker nodes') resize_params = UpdateClusterParameters( kubernetes_worker_instances=num_worker_nodes) cluster_api.update_cluster(name, body=resize_params) LOGGER.debug(f'PKS: {self.host} accepted the request to resize the ' f'cluster: {name}') result['status_code'] = ACCEPTED return result
def get_cluster_info(self, name): """Get the details of a cluster with a given name in PKS environment. :param str name: Name of the cluster :return: Details of the cluster. :rtype: dict """ result = {} result['body'] = [] result['status_code'] = OK cluster_api = ClusterApi(api_client=self.pks_client) LOGGER.debug(f'Sending request to PKS: {self.host} to get details' f' of cluster with name: {name}') cluster = cluster_api.get_cluster(cluster_name=name) cluster_dict = cluster.to_dict() cluster_params_dict = cluster_dict.pop('parameters') cluster_dict.update(cluster_params_dict) LOGGER.debug(f'Received response from PKS: {self.host} on cluster:' f' {name} with details: {cluster_dict}') result['body'] = cluster_dict return result
def _list_clusters(self, data): """.""" result = [] try: cluster_api = ClusterApi(api_client=self.pks_client) self.pks_wire_logger.debug( f"Sending request to PKS: {self.pks_host_uri} " "to list all clusters") pks_clusters = cluster_api.list_clusters() self.pks_wire_logger.debug( f"Received response from PKS: {self.pks_host_uri} " f"on the list of clusters: {pks_clusters}") for pks_cluster in pks_clusters: cluster_info = pks_cluster.to_dict() cluster_info[K8S_PROVIDER_KEY] = K8sProvider.PKS self._restore_original_name(cluster_info) # Flatten the nested 'parameters' dict cluster_params_dict = cluster_info.pop('parameters') cluster_info.update(cluster_params_dict) self.update_cluster_with_vcd_info(cluster_info) result.append(cluster_info) except ApiException as err: SERVER_LOGGER.debug( f"Listing PKS clusters failed with error:\n {err}" ) # noqa: E501 raise PksServerError(err.status, err.body) return self._filter_clusters(result, **data)
def _delete_cluster(self, cluster_name): """Delete the cluster with a given name in PKS environment. :param str cluster_name: Name of the cluster """ result = {} cluster_api = ClusterApi(api_client=self.pks_client) LOGGER.debug(f"Sending request to PKS: {self.pks_host_uri} to delete " f"the cluster with name: {cluster_name}") try: cluster_api.delete_cluster(cluster_name=cluster_name) except ApiException as err: LOGGER.debug(f"Deleting cluster {cluster_name} failed with " f"error:\n {err}") raise PksServerError(err.status, err.body) # TODO() access self.pks_ctx and get hold of nst_info to cleanup dfw # rules LOGGER.debug(f"PKS: {self.pks_host_uri} accepted the request to delete" f" the cluster: {cluster_name}") result = {} result['cluster_name'] = cluster_name result['task_status'] = 'in progress' return result
def _list_clusters(self): """Get list of clusters in PKS environment. :return: a list of cluster-dictionaries :rtype: list """ cluster_api = ClusterApi(api_client=self.pks_client) LOGGER.debug(f"Sending request to PKS: {self.pks_host_uri} " f"to list all clusters") try: clusters = cluster_api.list_clusters() except ApiException as err: LOGGER.debug(f"Listing PKS clusters failed with error:\n {err}") raise PksServerError(err.status, err.body) list_of_cluster_dicts = [] for cluster in clusters: cluster_dict = { 'name': cluster.name, 'plan-name': cluster.plan_name, 'uuid': cluster.uuid, 'status': cluster.last_action_state, 'last-action': cluster.last_action, 'k8_master_ips': cluster.kubernetes_master_ips, 'compute-profile-name': cluster.compute_profile_name, 'worker_count': cluster.parameters.kubernetes_worker_instances } list_of_cluster_dicts.append(cluster_dict) LOGGER.debug(f"Received response from PKS: {self.pks_host_uri} on the" f" list of clusters: {list_of_cluster_dicts}") return list_of_cluster_dicts
def _create_cluster(self, cluster_name, node_count, pks_plan, pks_ext_host, compute_profile=None, **kwargs): """Create cluster in PKS environment. :param str cluster_name: Name of the cluster :param str plan: PKS plan. It should be one of the three plans that PKS supports. :param str external_host_name: User-preferred external hostname of the K8 cluster :param str compute_profile: Name of the compute profile :return: Details of the cluster :rtype: dict """ # TODO(ClusterSpec) Create an inner class "ClusterSpec" # in abstract_broker.py and have subclasses define and use it # as instance variable. # Method 'Create_cluster' in VcdBroker and PksBroker should take # ClusterSpec either as a param (or) # read from instance variable (if needed only). compute_profile = compute_profile \ if compute_profile else self.compute_profile cluster_api = ClusterApi(api_client=self.pks_client) cluster_params = \ ClusterParameters(kubernetes_master_host=pks_ext_host, kubernetes_worker_instances=node_count) cluster_request = ClusterRequest(name=cluster_name, plan_name=pks_plan, parameters=cluster_params, compute_profile_name=compute_profile) LOGGER.debug(f"Sending request to PKS: {self.pks_host_uri} to create " f"cluster of name: {cluster_name}") try: cluster = cluster_api.add_cluster(cluster_request) except ApiException as err: LOGGER.debug(f"Creating cluster {cluster_name} in PKS failed with " f"error:\n {err}") raise PksServerError(err.status, err.body) cluster_dict = cluster.to_dict() # Flattening the dictionary cluster_params_dict = cluster_dict.pop('parameters') cluster_dict.update(cluster_params_dict) LOGGER.debug(f"PKS: {self.pks_host_uri} accepted the request to create" f" cluster: {cluster_name}") # TODO() access self.pks_ctx to get hold of nsxt_info and create dfw # rules return cluster_dict
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 resize_cluster(self, **kwargs): """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 """ data = kwargs[KwargKey.DATA] cluster_name = data[RequestKey.CLUSTER_NAME] num_workers = data[RequestKey.NUM_WORKERS] qualified_cluster_name = self._append_user_id(cluster_name) if (self.context.client.is_sysadmin() or self.context.user.has_org_admin_rights): cluster_info = self._get_cluster_info(data) qualified_cluster_name = cluster_info['pks_cluster_name'] self._check_cluster_isolation(cluster_name, qualified_cluster_name) result = {} cluster_api = ClusterApi(api_client=self.pks_client) self.pks_wire_logger.debug(f"Sending request to" f" PKS:{self.pks_host_uri} to resize" f" the cluster with name:" f"{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: SERVER_LOGGER.debug(f"Resizing cluster {qualified_cluster_name}" f" failed with error:\n {err}") raise PksServerError(err.status, err.body) self.pks_wire_logger.debug(f"PKS: {self.pks_host_uri} accepted the" f" request to resize the cluster: " f" {qualified_cluster_name}") result['name'] = qualified_cluster_name result['task_status'] = 'in progress' self._restore_original_name(result) if not self.context.client.is_sysadmin(): self._filter_sensitive_pks_properties(result) return result
def _create_cluster(self, *args, cluster_name, num_workers, pks_plan_name, pks_ext_host): """Create cluster in PKS environment. Creates Distributed Firewall rules in NSX-T to isolate the cluster network from other clusters. :param str cluster_name: Name of the cluster :param str plan: PKS plan. It should be one of the three plans that PKS supports. :param str external_host_name: User-preferred external hostname of the K8 cluster :return: Details of the cluster :rtype: dict """ cluster_api = ClusterApi(api_client=self.client) cluster_params = \ ClusterParameters(kubernetes_master_host=pks_ext_host, kubernetes_worker_instances=num_workers) cluster_request = \ ClusterRequest(name=cluster_name, plan_name=pks_plan_name, parameters=cluster_params, compute_profile_name=self.compute_profile) try: LOGGER.debug( f"Sending request to PKS: {self.pks_host_uri} to create " f"cluster of name: {cluster_name}") cluster = cluster_api.add_cluster(cluster_request) LOGGER.debug( f"PKS: {self.pks_host_uri} accepted the request to create" f" cluster: {cluster_name}") except ApiException as err: LOGGER.debug(f"Creating cluster {cluster_name} in PKS failed with " f"error:\n {err}") raise PksServerError(err.status, err.body) cluster_info = cluster.to_dict() # Flattening the dictionary cluster_params_dict = cluster_info.pop('parameters') cluster_info.update(cluster_params_dict) return cluster_info
def create_cluster(self, name, plan, external_host_name='cluster.pks.local', network_profile=None, compute_profile=None): """Create cluster in PKS environment. :param str name: Name of the cluster :param str plan: PKS plan. It should be one of {Plan 1, Plan 2, Plan 3} that PKS supports. :param str external_host_name: User-preferred external hostname of the K8 cluster :param str network_profile: Name of the network profile :param str compute_profile: Name of the compute profile :return: Details of the cluster. :rtype: dict """ # TODO() Invalidate cluster names containing '-' character. result = {} result['body'] = [] cluster_api = ClusterApi(api_client=self.pks_client) cluster_params = ClusterParameters( kubernetes_master_host=external_host_name, nsxt_network_profile=network_profile, compute_profile=compute_profile) cluster_request = ClusterRequest(name=name, plan_name=plan, parameters=cluster_params) LOGGER.debug(f'Sending request to PKS: {self.host} to create cluster' f' of name: {name}') cluster = cluster_api.add_cluster(cluster_request) cluster_dict = cluster.to_dict() cluster_params_dict = cluster_dict.pop('parameters') cluster_dict.update(cluster_params_dict) LOGGER.debug(f'PKS: {self.host} accepted the request to create' f' cluster: {name}') result['body'] = cluster_dict result['status_code'] = ACCEPTED return result
def _get_cluster_config(self, cluster_name): """Get the configuration of the cluster with the given name in PKS. :param str cluster_name: Name of the cluster :return: Configuration of the cluster. :rtype: str """ cluster_api = ClusterApi(api_client=self.pks_client) 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=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 cluster_config
def delete_cluster(self, name): """Delete the cluster with a given name in PKS environment. :param str name: Name of the cluster :return: None """ result = {} result['body'] = [] cluster_api = ClusterApi(api_client=self.pks_client) LOGGER.debug(f'Sending request to PKS: {self.host} to delete the ' f'cluster with name: {name}') cluster_api.delete_cluster(cluster_name=name) LOGGER.debug(f'PKS: {self.host} accepted the request to delete the ' f'cluster: {name}') result['status_code'] = ACCEPTED return result
def get_cluster_config(self, **kwargs): """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 """ data = kwargs[KwargKey.DATA] cluster_name = data[RequestKey.CLUSTER_NAME] qualified_cluster_name = self._append_user_id(cluster_name) if (self.context.client.is_sysadmin() or self.context.user.has_org_admin_rights): cluster_info = self._get_cluster_info(data) qualified_cluster_name = cluster_info['pks_cluster_name'] self._check_cluster_isolation(cluster_name, qualified_cluster_name) cluster_api = ClusterApi(api_client=self.pks_client) self.pks_wire_logger.debug( f"Sending request to PKS: {self.pks_host_uri} to get" # noqa: E501 f" kubectl configuration of cluster with name: " # noqa: E501 f"{qualified_cluster_name}") config = cluster_api.create_user(cluster_name=qualified_cluster_name) self.pks_wire_logger.debug( f"Received response from PKS: {self.pks_host_uri} on " # noqa: E501 f"cluster: {qualified_cluster_name} with details: " # noqa: E501 f"{config}") cluster_config = yaml.safe_dump(config, default_flow_style=False) return self.filter_traces_of_user_context(cluster_config)