1 ##############################################################################
2 # Copyright (c) 2017 Huawei Technologies Co.,Ltd.
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
11 from kubernetes import client
12 from kubernetes import config
13 from kubernetes.client.rest import ApiException
15 from yardstick.common import constants as consts
16 from yardstick.common import exceptions
19 LOG = logging.getLogger(__name__)
20 LOG.setLevel(logging.DEBUG)
23 def get_core_api(): # pragma: no cover
25 config.load_kube_config(config_file=consts.K8S_CONF_FILE)
27 raise exceptions.KubernetesConfigFileNotFound()
28 return client.CoreV1Api()
31 def get_extensions_v1beta_api():
33 config.load_kube_config(config_file=consts.K8S_CONF_FILE)
35 raise exceptions.KubernetesConfigFileNotFound()
36 return client.ApiextensionsV1beta1Api()
39 def get_custom_objects_api():
41 config.load_kube_config(config_file=consts.K8S_CONF_FILE)
43 raise exceptions.KubernetesConfigFileNotFound()
44 return client.CustomObjectsApi()
47 def get_node_list(**kwargs): # pragma: no cover
48 core_v1_api = get_core_api()
50 return core_v1_api.list_node(**kwargs)
52 LOG.exception('Get node list failed')
56 def create_service(template,
59 **kwargs): # pragma: no cover
60 # pylint: disable=unused-argument
61 core_v1_api = get_core_api()
62 metadata = client.V1ObjectMeta(**template.get('metadata', {}))
64 ports = [client.V1ServicePort(**port) for port in
65 template.get('spec', {}).get('ports', [])]
66 template['spec']['ports'] = ports
67 spec = client.V1ServiceSpec(**template.get('spec', {}))
69 service = client.V1Service(metadata=metadata, spec=spec)
72 core_v1_api.create_namespaced_service('default', service)
74 LOG.exception('Create Service failed')
78 def delete_service(name, namespace='default', skip_codes=None, **kwargs):
79 skip_codes = [] if not skip_codes else skip_codes
80 core_v1_api = get_core_api()
82 body = client.V1DeleteOptions()
83 core_v1_api.delete_namespaced_service(name, namespace, body, **kwargs)
84 except ApiException as e:
85 if e.status in skip_codes:
88 raise exceptions.KubernetesApiException(
89 action='delete', resource='Service')
92 def get_service_list(namespace='default', **kwargs):
93 core_v1_api = get_core_api()
95 return core_v1_api.list_namespaced_service(namespace, **kwargs)
97 LOG.exception('Get Service list failed')
101 def get_service_by_name(name): # pragma: no cover
102 service_list = get_service_list()
103 return next((s.spec for s in service_list.items if s.metadata.name == name), None)
106 def create_replication_controller(template,
109 **kwargs): # pragma: no cover
110 # pylint: disable=unused-argument
111 core_v1_api = get_core_api()
113 core_v1_api.create_namespaced_replication_controller(namespace,
117 LOG.exception('Create replication controller failed')
121 def delete_replication_controller(name,
126 # pylint: disable=unused-argument
127 skip_codes = [] if not skip_codes else skip_codes
128 core_v1_api = get_core_api()
129 body = kwargs.get('body', client.V1DeleteOptions())
130 kwargs.pop('body', None)
132 core_v1_api.delete_namespaced_replication_controller(name,
136 except ApiException as e:
137 if e.status in skip_codes:
140 raise exceptions.KubernetesApiException(
141 action='delete', resource='ReplicationController')
148 **kwargs): # pragma: no cover
149 # pylint: disable=unused-argument
150 skip_codes = [] if not skip_codes else skip_codes
151 core_v1_api = get_core_api()
152 body = kwargs.get('body', client.V1DeleteOptions())
153 kwargs.pop('body', None)
155 core_v1_api.delete_namespaced_pod(name,
159 except ApiException as e:
160 if e.status in skip_codes:
163 raise exceptions.KubernetesApiException(
164 action='delete', resource='Pod')
169 **kwargs): # pragma: no cover
170 core_v1_api = get_core_api()
172 resp = core_v1_api.read_namespaced_pod(name, namespace, **kwargs)
174 LOG.exception('Read pod failed')
180 def read_pod_status(name, namespace='default', **kwargs): # pragma: no cover
181 # pylint: disable=unused-argument
182 return read_pod(name).status.phase
185 def create_config_map(name,
189 **kwargs): # pragma: no cover
190 # pylint: disable=unused-argument
191 core_v1_api = get_core_api()
192 metadata = client.V1ObjectMeta(name=name)
193 body = client.V1ConfigMap(data=data, metadata=metadata)
195 core_v1_api.create_namespaced_config_map(namespace, body, **kwargs)
197 LOG.exception('Create config map failed')
201 def delete_config_map(name,
206 # pylint: disable=unused-argument
207 skip_codes = [] if not skip_codes else skip_codes
208 core_v1_api = get_core_api()
209 body = kwargs.get('body', client.V1DeleteOptions())
210 kwargs.pop('body', None)
212 core_v1_api.delete_namespaced_config_map(name,
216 except ApiException as e:
217 if e.status in skip_codes:
220 raise exceptions.KubernetesApiException(
221 action='delete', resource='ConfigMap')
224 def create_custom_resource_definition(body):
225 api = get_extensions_v1beta_api()
226 body_obj = client.V1beta1CustomResourceDefinition(
227 spec=body['spec'], metadata=body['metadata'])
229 api.create_custom_resource_definition(body_obj)
231 # NOTE(ralonsoh): bug in kubernetes-client/python 6.0.0
232 # https://github.com/kubernetes-client/python/issues/491
235 raise exceptions.KubernetesApiException(
236 action='create', resource='CustomResourceDefinition')
239 def delete_custom_resource_definition(name, skip_codes=None):
240 skip_codes = [] if not skip_codes else skip_codes
241 api = get_extensions_v1beta_api()
242 body_obj = client.V1DeleteOptions()
244 api.delete_custom_resource_definition(name, body_obj)
245 except ApiException as e:
246 if e.status in skip_codes:
249 raise exceptions.KubernetesApiException(
250 action='delete', resource='CustomResourceDefinition')
253 def get_custom_resource_definition(kind):
254 api = get_extensions_v1beta_api()
256 crd_list = api.list_custom_resource_definition()
257 for crd_obj in (crd_obj for crd_obj in crd_list.items
258 if crd_obj.spec.names.kind == kind):
262 raise exceptions.KubernetesApiException(
263 action='delete', resource='CustomResourceDefinition')
266 def get_network(scope, group, version, plural, name, namespace='default'):
267 api = get_custom_objects_api()
269 if scope == consts.SCOPE_CLUSTER:
270 network = api.get_cluster_custom_object(group, version, plural, name)
272 network = api.get_namespaced_custom_object(
273 group, version, namespace, plural, name)
274 except ApiException as e:
275 if e.status in [404]:
278 raise exceptions.KubernetesApiException(
279 action='get', resource='Custom Object: Network')
283 def create_network(scope, group, version, plural, body, name, namespace='default'):
284 api = get_custom_objects_api()
285 if get_network(scope, group, version, plural, name, namespace):
286 logging.info('Network %s already exists', name)
289 if scope == consts.SCOPE_CLUSTER:
290 api.create_cluster_custom_object(group, version, plural, body)
292 api.create_namespaced_custom_object(
293 group, version, namespace, plural, body)
295 raise exceptions.KubernetesApiException(
296 action='create', resource='Custom Object: Network')
299 def delete_network(scope, group, version, plural, name, namespace='default', skip_codes=None):
300 skip_codes = [] if not skip_codes else skip_codes
301 api = get_custom_objects_api()
303 if scope == consts.SCOPE_CLUSTER:
304 api.delete_cluster_custom_object(group, version, plural, name, {})
306 api.delete_namespaced_custom_object(
307 group, version, namespace, plural, name, {})
308 except ApiException as e:
309 if e.status in skip_codes:
312 raise exceptions.KubernetesApiException(
313 action='delete', resource='Custom Object: Network')
316 def get_pod_list(namespace='default'): # pragma: no cover
317 core_v1_api = get_core_api()
319 return core_v1_api.list_namespaced_pod(namespace=namespace)
321 LOG.exception('Get pod list failed')
325 def get_pod_by_name(name): # pragma: no cover
326 pod_list = get_pod_list()
327 return next((n for n in pod_list.items if n.metadata.name.startswith(name)), None)
330 def get_volume_types():
331 """Return the "volume" types supported by the current API"""
332 return [vtype for vtype in client.V1Volume.attribute_map.values()