kubernetes_utils: avoid 404 error code in delete_replication_controller()
[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                       **kwargs):     # pragma: no cover
205     # pylint: disable=unused-argument
206     core_v1_api = get_core_api()
207     body = kwargs.get('body', client.V1DeleteOptions())
208     kwargs.pop('body', None)
209     try:
210         core_v1_api.delete_namespaced_config_map(name,
211                                                  namespace,
212                                                  body,
213                                                  **kwargs)
214     except ApiException:
215         LOG.exception('Delete config map failed')
216         raise
217
218
219 def create_custom_resource_definition(body):
220     api = get_extensions_v1beta_api()
221     body_obj = client.V1beta1CustomResourceDefinition(
222         spec=body['spec'], metadata=body['metadata'])
223     try:
224         api.create_custom_resource_definition(body_obj)
225     except ValueError:
226         # NOTE(ralonsoh): bug in kubernetes-client/python 6.0.0
227         # https://github.com/kubernetes-client/python/issues/491
228         pass
229     except ApiException:
230         raise exceptions.KubernetesApiException(
231             action='create', resource='CustomResourceDefinition')
232
233
234 def delete_custom_resource_definition(name, skip_codes=None):
235     skip_codes = [] if not skip_codes else skip_codes
236     api = get_extensions_v1beta_api()
237     body_obj = client.V1DeleteOptions()
238     try:
239         api.delete_custom_resource_definition(name, body_obj)
240     except ApiException as e:
241         if e.status in skip_codes:
242             LOG.info(e.reason)
243         else:
244             raise exceptions.KubernetesApiException(
245                 action='delete', resource='CustomResourceDefinition')
246
247
248 def get_custom_resource_definition(kind):
249     api = get_extensions_v1beta_api()
250     try:
251         crd_list = api.list_custom_resource_definition()
252         for crd_obj in (crd_obj for crd_obj in crd_list.items
253                         if crd_obj.spec.names.kind == kind):
254             return crd_obj
255         return None
256     except ApiException:
257         raise exceptions.KubernetesApiException(
258             action='delete', resource='CustomResourceDefinition')
259
260
261 def create_network(scope, group, version, plural, body, namespace='default'):
262     api = get_custom_objects_api()
263     try:
264         if scope == consts.SCOPE_CLUSTER:
265             api.create_cluster_custom_object(group, version, plural, body)
266         else:
267             api.create_namespaced_custom_object(
268                 group, version, namespace, plural, body)
269     except ApiException:
270         raise exceptions.KubernetesApiException(
271             action='create', resource='Custom Object: Network')
272
273
274 def delete_network(scope, group, version, plural, name, namespace='default', skip_codes=None):
275     skip_codes = [] if not skip_codes else skip_codes
276     api = get_custom_objects_api()
277     try:
278         if scope == consts.SCOPE_CLUSTER:
279             api.delete_cluster_custom_object(group, version, plural, name, {})
280         else:
281             api.delete_namespaced_custom_object(
282                 group, version, namespace, plural, name, {})
283     except ApiException as e:
284         if e.status in skip_codes:
285             LOG.info(e.reason)
286         else:
287             raise exceptions.KubernetesApiException(
288                 action='delete', resource='Custom Object: Network')
289
290
291 def get_pod_list(namespace='default'):      # pragma: no cover
292     core_v1_api = get_core_api()
293     try:
294         return core_v1_api.list_namespaced_pod(namespace=namespace)
295     except ApiException:
296         LOG.exception('Get pod list failed')
297         raise
298
299
300 def get_pod_by_name(name):  # pragma: no cover
301     pod_list = get_pod_list()
302     return next((n for n in pod_list.items if n.metadata.name.startswith(name)), None)
303
304
305 def get_volume_types():
306     """Return the "volume" types supported by the current API"""
307     return [vtype for vtype in client.V1Volume.attribute_map.values()
308             if vtype != 'name']