Merge "Add test suite for scenario "opnfv_os-ovn-nofeature-ha""
[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                                   skip_codes=None,
125                                   **kwargs):
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)
131     try:
132         core_v1_api.delete_namespaced_replication_controller(name,
133                                                              namespace,
134                                                              body,
135                                                              **kwargs)
136     except ApiException as e:
137         if e.status in skip_codes:
138             LOG.info(e.reason)
139         else:
140             raise exceptions.KubernetesApiException(
141                 action='delete', resource='ReplicationController')
142
143
144 def delete_pod(name,
145                namespace='default',
146                wait=False,
147                skip_codes=None,
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)
154     try:
155         core_v1_api.delete_namespaced_pod(name,
156                                           namespace,
157                                           body,
158                                           **kwargs)
159     except ApiException as e:
160         if e.status in skip_codes:
161             LOG.info(e.reason)
162         else:
163             raise exceptions.KubernetesApiException(
164                 action='delete', resource='Pod')
165
166
167 def read_pod(name,
168              namespace='default',
169              **kwargs):  # pragma: no cover
170     core_v1_api = get_core_api()
171     try:
172         resp = core_v1_api.read_namespaced_pod(name, namespace, **kwargs)
173     except ApiException:
174         LOG.exception('Read pod failed')
175         raise
176     else:
177         return resp
178
179
180 def read_pod_status(name, namespace='default', **kwargs):   # pragma: no cover
181     # pylint: disable=unused-argument
182     return read_pod(name).status.phase
183
184
185 def create_config_map(name,
186                       data,
187                       namespace='default',
188                       wait=False,
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)
194     try:
195         core_v1_api.create_namespaced_config_map(namespace, body, **kwargs)
196     except ApiException:
197         LOG.exception('Create config map failed')
198         raise
199
200
201 def delete_config_map(name,
202                       namespace='default',
203                       wait=False,
204                       skip_codes=None,
205                       **kwargs):
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)
211     try:
212         core_v1_api.delete_namespaced_config_map(name,
213                                                  namespace,
214                                                  body,
215                                                  **kwargs)
216     except ApiException as e:
217         if e.status in skip_codes:
218             LOG.info(e.reason)
219         else:
220             raise exceptions.KubernetesApiException(
221                 action='delete', resource='ConfigMap')
222
223
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'])
228     try:
229         api.create_custom_resource_definition(body_obj)
230     except ValueError:
231         # NOTE(ralonsoh): bug in kubernetes-client/python 6.0.0
232         # https://github.com/kubernetes-client/python/issues/491
233         pass
234     except ApiException:
235         raise exceptions.KubernetesApiException(
236             action='create', resource='CustomResourceDefinition')
237
238
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()
243     try:
244         api.delete_custom_resource_definition(name, body_obj)
245     except ApiException as e:
246         if e.status in skip_codes:
247             LOG.info(e.reason)
248         else:
249             raise exceptions.KubernetesApiException(
250                 action='delete', resource='CustomResourceDefinition')
251
252
253 def get_custom_resource_definition(kind):
254     api = get_extensions_v1beta_api()
255     try:
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):
259             return crd_obj
260         return None
261     except ApiException:
262         raise exceptions.KubernetesApiException(
263             action='delete', resource='CustomResourceDefinition')
264
265
266 def get_network(scope, group, version, plural, name, namespace='default'):
267     api = get_custom_objects_api()
268     try:
269         if scope == consts.SCOPE_CLUSTER:
270             network = api.get_cluster_custom_object(group, version, plural, name)
271         else:
272             network = api.get_namespaced_custom_object(
273                 group, version, namespace, plural, name)
274     except ApiException as e:
275         if e.status in [404]:
276             return
277         else:
278             raise exceptions.KubernetesApiException(
279                 action='get', resource='Custom Object: Network')
280     return network
281
282
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)
287         return
288     try:
289         if scope == consts.SCOPE_CLUSTER:
290             api.create_cluster_custom_object(group, version, plural, body)
291         else:
292             api.create_namespaced_custom_object(
293                 group, version, namespace, plural, body)
294     except ApiException:
295         raise exceptions.KubernetesApiException(
296             action='create', resource='Custom Object: Network')
297
298
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()
302     try:
303         if scope == consts.SCOPE_CLUSTER:
304             api.delete_cluster_custom_object(group, version, plural, name, {})
305         else:
306             api.delete_namespaced_custom_object(
307                 group, version, namespace, plural, name, {})
308     except ApiException as e:
309         if e.status in skip_codes:
310             LOG.info(e.reason)
311         else:
312             raise exceptions.KubernetesApiException(
313                 action='delete', resource='Custom Object: Network')
314
315
316 def get_pod_list(namespace='default'):      # pragma: no cover
317     core_v1_api = get_core_api()
318     try:
319         return core_v1_api.list_namespaced_pod(namespace=namespace)
320     except ApiException:
321         LOG.exception('Get pod list failed')
322         raise
323
324
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)
328
329
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()
333             if vtype != 'name']