c90f73e43d740016e48b01553c090300c28628b1
[yardstick.git] / yardstick / common / kubernetes_utils.py
1 ##############################################################################
2 # Copyright (c) 2017 Huawei Technologies Co.,Ltd.
3 #
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 ##############################################################################
9 import logging
10
11 from kubernetes import client
12 from kubernetes import config
13 from kubernetes.client.rest import ApiException
14
15 from yardstick.common import constants as consts
16 from yardstick.common import exceptions
17
18
19 LOG = logging.getLogger(__name__)
20 LOG.setLevel(logging.DEBUG)
21
22
23 def get_core_api():     # pragma: no cover
24     try:
25         config.load_kube_config(config_file=consts.K8S_CONF_FILE)
26     except IOError:
27         raise exceptions.KubernetesConfigFileNotFound()
28     return client.CoreV1Api()
29
30
31 def get_extensions_v1beta_api():
32     try:
33         config.load_kube_config(config_file=consts.K8S_CONF_FILE)
34     except IOError:
35         raise exceptions.KubernetesConfigFileNotFound()
36     return client.ApiextensionsV1beta1Api()
37
38
39 def get_custom_objects_api():
40     try:
41         config.load_kube_config(config_file=consts.K8S_CONF_FILE)
42     except IOError:
43         raise exceptions.KubernetesConfigFileNotFound()
44     return client.CustomObjectsApi()
45
46
47 def get_node_list(**kwargs):        # pragma: no cover
48     core_v1_api = get_core_api()
49     try:
50         return core_v1_api.list_node(**kwargs)
51     except ApiException:
52         LOG.exception('Get node list failed')
53         raise
54
55
56 def create_service(template,
57                    namespace='default',
58                    wait=False,
59                    **kwargs):       # pragma: no cover
60     # pylint: disable=unused-argument
61     core_v1_api = get_core_api()
62     metadata = client.V1ObjectMeta(**template.get('metadata', {}))
63
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', {}))
68
69     service = client.V1Service(metadata=metadata, spec=spec)
70
71     try:
72         core_v1_api.create_namespaced_service('default', service)
73     except ApiException:
74         LOG.exception('Create Service failed')
75         raise
76
77
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()
81     try:
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:
86             LOG.info(e.reason)
87         else:
88             raise exceptions.KubernetesApiException(
89                 action='delete', resource='Service')
90
91
92 def get_service_list(namespace='default', **kwargs):
93     core_v1_api = get_core_api()
94     try:
95         return core_v1_api.list_namespaced_service(namespace, **kwargs)
96     except ApiException:
97         LOG.exception('Get Service list failed')
98         raise
99
100
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)
104
105
106 def create_replication_controller(template,
107                                   namespace='default',
108                                   wait=False,
109                                   **kwargs):    # pragma: no cover
110     # pylint: disable=unused-argument
111     core_v1_api = get_core_api()
112     try:
113         core_v1_api.create_namespaced_replication_controller(namespace,
114                                                              template,
115                                                              **kwargs)
116     except ApiException:
117         LOG.exception('Create replication controller failed')
118         raise
119
120
121 def delete_replication_controller(name,
122                                   namespace='default',
123                                   wait=False,
124                                   **kwargs):    # pragma: no cover
125     # pylint: disable=unused-argument
126     core_v1_api = get_core_api()
127     body = kwargs.get('body', client.V1DeleteOptions())
128     kwargs.pop('body', None)
129     try:
130         core_v1_api.delete_namespaced_replication_controller(name,
131                                                              namespace,
132                                                              body,
133                                                              **kwargs)
134     except ApiException:
135         LOG.exception('Delete replication controller failed')
136         raise
137
138
139 def delete_pod(name,
140                namespace='default',
141                wait=False,
142                skip_codes=None,
143                **kwargs):    # pragma: no cover
144     # pylint: disable=unused-argument
145     skip_codes = [] if not skip_codes else skip_codes
146     core_v1_api = get_core_api()
147     body = kwargs.get('body', client.V1DeleteOptions())
148     kwargs.pop('body', None)
149     try:
150         core_v1_api.delete_namespaced_pod(name,
151                                           namespace,
152                                           body,
153                                           **kwargs)
154     except ApiException as e:
155         if e.status in skip_codes:
156             LOG.info(e.reason)
157         else:
158             raise exceptions.KubernetesApiException(
159                 action='delete', resource='Pod')
160
161
162 def read_pod(name,
163              namespace='default',
164              **kwargs):  # pragma: no cover
165     core_v1_api = get_core_api()
166     try:
167         resp = core_v1_api.read_namespaced_pod(name, namespace, **kwargs)
168     except ApiException:
169         LOG.exception('Read pod failed')
170         raise
171     else:
172         return resp
173
174
175 def read_pod_status(name, namespace='default', **kwargs):   # pragma: no cover
176     # pylint: disable=unused-argument
177     return read_pod(name).status.phase
178
179
180 def create_config_map(name,
181                       data,
182                       namespace='default',
183                       wait=False,
184                       **kwargs):   # pragma: no cover
185     # pylint: disable=unused-argument
186     core_v1_api = get_core_api()
187     metadata = client.V1ObjectMeta(name=name)
188     body = client.V1ConfigMap(data=data, metadata=metadata)
189     try:
190         core_v1_api.create_namespaced_config_map(namespace, body, **kwargs)
191     except ApiException:
192         LOG.exception('Create config map failed')
193         raise
194
195
196 def delete_config_map(name,
197                       namespace='default',
198                       wait=False,
199                       **kwargs):     # pragma: no cover
200     # pylint: disable=unused-argument
201     core_v1_api = get_core_api()
202     body = kwargs.get('body', client.V1DeleteOptions())
203     kwargs.pop('body', None)
204     try:
205         core_v1_api.delete_namespaced_config_map(name,
206                                                  namespace,
207                                                  body,
208                                                  **kwargs)
209     except ApiException:
210         LOG.exception('Delete config map failed')
211         raise
212
213
214 def create_custom_resource_definition(body):
215     api = get_extensions_v1beta_api()
216     body_obj = client.V1beta1CustomResourceDefinition(
217         spec=body['spec'], metadata=body['metadata'])
218     try:
219         api.create_custom_resource_definition(body_obj)
220     except ValueError:
221         # NOTE(ralonsoh): bug in kubernetes-client/python 6.0.0
222         # https://github.com/kubernetes-client/python/issues/491
223         pass
224     except ApiException:
225         raise exceptions.KubernetesApiException(
226             action='create', resource='CustomResourceDefinition')
227
228
229 def delete_custom_resource_definition(name, skip_codes=None):
230     skip_codes = [] if not skip_codes else skip_codes
231     api = get_extensions_v1beta_api()
232     body_obj = client.V1DeleteOptions()
233     try:
234         api.delete_custom_resource_definition(name, body_obj)
235     except ApiException as e:
236         if e.status in skip_codes:
237             LOG.info(e.reason)
238         else:
239             raise exceptions.KubernetesApiException(
240                 action='delete', resource='CustomResourceDefinition')
241
242
243 def get_custom_resource_definition(kind):
244     api = get_extensions_v1beta_api()
245     try:
246         crd_list = api.list_custom_resource_definition()
247         for crd_obj in (crd_obj for crd_obj in crd_list.items
248                         if crd_obj.spec.names.kind == kind):
249             return crd_obj
250         return None
251     except ApiException:
252         raise exceptions.KubernetesApiException(
253             action='delete', resource='CustomResourceDefinition')
254
255
256 def create_network(scope, group, version, plural, body, namespace='default'):
257     api = get_custom_objects_api()
258     try:
259         if scope == consts.SCOPE_CLUSTER:
260             api.create_cluster_custom_object(group, version, plural, body)
261         else:
262             api.create_namespaced_custom_object(
263                 group, version, namespace, plural, body)
264     except ApiException:
265         raise exceptions.KubernetesApiException(
266             action='create', resource='Custom Object: Network')
267
268
269 def delete_network(scope, group, version, plural, name, namespace='default', skip_codes=None):
270     skip_codes = [] if not skip_codes else skip_codes
271     api = get_custom_objects_api()
272     try:
273         if scope == consts.SCOPE_CLUSTER:
274             api.delete_cluster_custom_object(group, version, plural, name, {})
275         else:
276             api.delete_namespaced_custom_object(
277                 group, version, namespace, plural, name, {})
278     except ApiException as e:
279         if e.status in skip_codes:
280             LOG.info(e.reason)
281         else:
282             raise exceptions.KubernetesApiException(
283                 action='delete', resource='Custom Object: Network')
284
285
286 def get_pod_list(namespace='default'):      # pragma: no cover
287     core_v1_api = get_core_api()
288     try:
289         return core_v1_api.list_namespaced_pod(namespace=namespace)
290     except ApiException:
291         LOG.exception('Get pod list failed')
292         raise
293
294
295 def get_pod_by_name(name):  # pragma: no cover
296     pod_list = get_pod_list()
297     return next((n for n in pod_list.items if n.metadata.name.startswith(name)), None)
298
299
300 def get_volume_types():
301     """Return the "volume" types supported by the current API"""
302     return [vtype for vtype in client.V1Volume.attribute_map.values()
303             if vtype != 'name']