X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=yardstick%2Fcommon%2Fkubernetes_utils.py;h=323f13abbff366a38cecd2b132270f1c9c776b26;hb=8a52d114404a03b4adbb49ff7f221819502bf672;hp=e4c23283016280f597649fd9726c92914ca79c2e;hpb=d29df23ae5057fe0ccded6f8d8f3e36a084a78b3;p=yardstick.git diff --git a/yardstick/common/kubernetes_utils.py b/yardstick/common/kubernetes_utils.py index e4c232830..323f13abb 100644 --- a/yardstick/common/kubernetes_utils.py +++ b/yardstick/common/kubernetes_utils.py @@ -13,6 +13,8 @@ from kubernetes import config from kubernetes.client.rest import ApiException from yardstick.common import constants as consts +from yardstick.common import exceptions + LOG = logging.getLogger(__name__) LOG.setLevel(logging.DEBUG) @@ -22,17 +24,90 @@ def get_core_api(): # pragma: no cover try: config.load_kube_config(config_file=consts.K8S_CONF_FILE) except IOError: - LOG.exception('config file not found') + raise exceptions.KubernetesConfigFileNotFound() + return client.CoreV1Api() + + +def get_extensions_v1beta_api(): + try: + config.load_kube_config(config_file=consts.K8S_CONF_FILE) + except IOError: + raise exceptions.KubernetesConfigFileNotFound() + return client.ApiextensionsV1beta1Api() + + +def get_custom_objects_api(): + try: + config.load_kube_config(config_file=consts.K8S_CONF_FILE) + except IOError: + raise exceptions.KubernetesConfigFileNotFound() + return client.CustomObjectsApi() + + +def get_node_list(**kwargs): # pragma: no cover + core_v1_api = get_core_api() + try: + return core_v1_api.list_node(**kwargs) + except ApiException: + LOG.exception('Get node list failed') raise - return client.CoreV1Api() + +def create_service(template, + namespace='default', + wait=False, + **kwargs): # pragma: no cover + # pylint: disable=unused-argument + core_v1_api = get_core_api() + metadata = client.V1ObjectMeta(**template.get('metadata', {})) + + ports = [client.V1ServicePort(**port) for port in + template.get('spec', {}).get('ports', [])] + template['spec']['ports'] = ports + spec = client.V1ServiceSpec(**template.get('spec', {})) + + service = client.V1Service(metadata=metadata, spec=spec) + + try: + core_v1_api.create_namespaced_service('default', service) + except ApiException: + LOG.exception('Create Service failed') + raise + + +def delete_service(name, namespace='default', skip_codes=None, **kwargs): + skip_codes = [] if not skip_codes else skip_codes + core_v1_api = get_core_api() + try: + body = client.V1DeleteOptions() + core_v1_api.delete_namespaced_service(name, namespace, body, **kwargs) + except ApiException as e: + if e.status in skip_codes: + LOG.info(e.reason) + else: + raise exceptions.KubernetesApiException( + action='delete', resource='Service') + + +def get_service_list(namespace='default', **kwargs): + core_v1_api = get_core_api() + try: + return core_v1_api.list_namespaced_service(namespace, **kwargs) + except ApiException: + LOG.exception('Get Service list failed') + raise + + +def get_service_by_name(name): # pragma: no cover + service_list = get_service_list() + return next((s.spec for s in service_list.items if s.metadata.name == name), None) def create_replication_controller(template, namespace='default', wait=False, **kwargs): # pragma: no cover - + # pylint: disable=unused-argument core_v1_api = get_core_api() try: core_v1_api.create_namespaced_replication_controller(namespace, @@ -46,8 +121,10 @@ def create_replication_controller(template, def delete_replication_controller(name, namespace='default', wait=False, - **kwargs): # pragma: no cover - + skip_codes=None, + **kwargs): + # pylint: disable=unused-argument + skip_codes = [] if not skip_codes else skip_codes core_v1_api = get_core_api() body = kwargs.get('body', client.V1DeleteOptions()) kwargs.pop('body', None) @@ -56,16 +133,21 @@ def delete_replication_controller(name, namespace, body, **kwargs) - except ApiException: - LOG.exception('Delete replication controller failed') - raise + except ApiException as e: + if e.status in skip_codes: + LOG.info(e.reason) + else: + raise exceptions.KubernetesApiException( + action='delete', resource='ReplicationController') def delete_pod(name, namespace='default', wait=False, + skip_codes=None, **kwargs): # pragma: no cover - + # pylint: disable=unused-argument + skip_codes = [] if not skip_codes else skip_codes core_v1_api = get_core_api() body = kwargs.get('body', client.V1DeleteOptions()) kwargs.pop('body', None) @@ -74,9 +156,12 @@ def delete_pod(name, namespace, body, **kwargs) - except ApiException: - LOG.exception('Delete pod failed') - raise + except ApiException as e: + if e.status in skip_codes: + LOG.info(e.reason) + else: + raise exceptions.KubernetesApiException( + action='delete', resource='Pod') def read_pod(name, @@ -93,6 +178,7 @@ def read_pod(name, def read_pod_status(name, namespace='default', **kwargs): # pragma: no cover + # pylint: disable=unused-argument return read_pod(name).status.phase @@ -101,6 +187,7 @@ def create_config_map(name, namespace='default', wait=False, **kwargs): # pragma: no cover + # pylint: disable=unused-argument core_v1_api = get_core_api() metadata = client.V1ObjectMeta(name=name) body = client.V1ConfigMap(data=data, metadata=metadata) @@ -114,7 +201,10 @@ def create_config_map(name, def delete_config_map(name, namespace='default', wait=False, - **kwargs): # pragma: no cover + skip_codes=None, + **kwargs): + # pylint: disable=unused-argument + skip_codes = [] if not skip_codes else skip_codes core_v1_api = get_core_api() body = kwargs.get('body', client.V1DeleteOptions()) kwargs.pop('body', None) @@ -123,9 +213,104 @@ def delete_config_map(name, namespace, body, **kwargs) + except ApiException as e: + if e.status in skip_codes: + LOG.info(e.reason) + else: + raise exceptions.KubernetesApiException( + action='delete', resource='ConfigMap') + + +def create_custom_resource_definition(body): + api = get_extensions_v1beta_api() + body_obj = client.V1beta1CustomResourceDefinition( + spec=body['spec'], metadata=body['metadata']) + try: + api.create_custom_resource_definition(body_obj) + except ValueError: + # NOTE(ralonsoh): bug in kubernetes-client/python 6.0.0 + # https://github.com/kubernetes-client/python/issues/491 + pass except ApiException: - LOG.exception('Delete config map failed') - raise + raise exceptions.KubernetesApiException( + action='create', resource='CustomResourceDefinition') + + +def delete_custom_resource_definition(name, skip_codes=None): + skip_codes = [] if not skip_codes else skip_codes + api = get_extensions_v1beta_api() + body_obj = client.V1DeleteOptions() + try: + api.delete_custom_resource_definition(name, body_obj) + except ApiException as e: + if e.status in skip_codes: + LOG.info(e.reason) + else: + raise exceptions.KubernetesApiException( + action='delete', resource='CustomResourceDefinition') + + +def get_custom_resource_definition(kind): + api = get_extensions_v1beta_api() + try: + crd_list = api.list_custom_resource_definition() + for crd_obj in (crd_obj for crd_obj in crd_list.items + if crd_obj.spec.names.kind == kind): + return crd_obj + return None + except ApiException: + raise exceptions.KubernetesApiException( + action='delete', resource='CustomResourceDefinition') + + +def get_network(scope, group, version, plural, name, namespace='default'): + api = get_custom_objects_api() + try: + if scope == consts.SCOPE_CLUSTER: + network = api.get_cluster_custom_object(group, version, plural, name) + else: + network = api.get_namespaced_custom_object( + group, version, namespace, plural, name) + except ApiException as e: + if e.status in [404]: + return + else: + raise exceptions.KubernetesApiException( + action='get', resource='Custom Object: Network') + return network + + +def create_network(scope, group, version, plural, body, name, namespace='default'): + api = get_custom_objects_api() + if get_network(scope, group, version, plural, name, namespace): + logging.info('Network %s already exists', name) + return + try: + if scope == consts.SCOPE_CLUSTER: + api.create_cluster_custom_object(group, version, plural, body) + else: + api.create_namespaced_custom_object( + group, version, namespace, plural, body) + except ApiException: + raise exceptions.KubernetesApiException( + action='create', resource='Custom Object: Network') + + +def delete_network(scope, group, version, plural, name, namespace='default', skip_codes=None): + skip_codes = [] if not skip_codes else skip_codes + api = get_custom_objects_api() + try: + if scope == consts.SCOPE_CLUSTER: + api.delete_cluster_custom_object(group, version, plural, name, {}) + else: + api.delete_namespaced_custom_object( + group, version, namespace, plural, name, {}) + except ApiException as e: + if e.status in skip_codes: + LOG.info(e.reason) + else: + raise exceptions.KubernetesApiException( + action='delete', resource='Custom Object: Network') def get_pod_list(namespace='default'): # pragma: no cover @@ -135,3 +320,14 @@ def get_pod_list(namespace='default'): # pragma: no cover except ApiException: LOG.exception('Get pod list failed') raise + + +def get_pod_by_name(name): # pragma: no cover + pod_list = get_pod_list() + return next((n for n in pod_list.items if n.metadata.name.startswith(name)), None) + + +def get_volume_types(): + """Return the "volume" types supported by the current API""" + return [vtype for vtype in client.V1Volume.attribute_map.values() + if vtype != 'name']