Merge "Change "monitor" to "assert" in SLA"
[yardstick.git] / yardstick / benchmark / contexts / kubernetes.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
10 from __future__ import absolute_import
11 import logging
12 import time
13 import pkg_resources
14
15 import paramiko
16
17 from yardstick.benchmark.contexts.base import Context
18 from yardstick.orchestrator import kubernetes
19 from yardstick.common import kubernetes_utils as k8s_utils
20 from yardstick.common import utils
21
22 LOG = logging.getLogger(__name__)
23 BITS_LENGTH = 2048
24
25
26 class KubernetesContext(Context):
27     """Class that handle nodes info"""
28
29     __context_type__ = "Kubernetes"
30
31     def __init__(self):
32         self.ssh_key = ''
33         self.key_path = ''
34         self.public_key_path = ''
35         self.template = None
36         super(KubernetesContext, self).__init__(host_name_separator='-')
37
38     def init(self, attrs):
39         super(KubernetesContext, self).init(attrs)
40
41         self.template = kubernetes.KubernetesTemplate(self.name, attrs)
42         self.ssh_key = '{}-key'.format(self.name)
43         self.key_path = self._get_key_path()
44         self.public_key_path = '{}.pub'.format(self.key_path)
45
46     def deploy(self):
47         LOG.info('Creating ssh key')
48         self._set_ssh_key()
49
50         self._create_crd()
51         self._create_networks()
52         LOG.info('Launch containers')
53         self._create_rcs()
54         self._create_services()
55         time.sleep(1)
56         self.template.get_rc_pods()
57
58         self._wait_until_running()
59
60     def undeploy(self):
61         self._delete_ssh_key()
62         self._delete_rcs()
63         self._delete_pods()
64         self._delete_services()
65         self._delete_networks()
66         self._delete_crd()
67
68         super(KubernetesContext, self).undeploy()
69
70     def _wait_until_running(self):
71         while not all(self._check_pod_status(p) for p in self.template.pods):
72             time.sleep(1)
73
74     def _check_pod_status(self, pod):
75         status = k8s_utils.read_pod_status(pod)
76         LOG.debug('%s:%s', pod, status)
77         if status == 'Failed':
78             LOG.error('Pod %s status is failed', pod)
79             raise RuntimeError
80         if status != 'Running':
81             return False
82         return True
83
84     def _create_services(self):
85         for obj in self.template.service_objs:
86             obj.create()
87
88     def _delete_services(self):
89         for obj in self.template.service_objs:
90             obj.delete()
91
92     def _create_rcs(self):
93         for obj in self.template.k8s_objs:
94             self._create_rc(obj.get_template())
95
96     def _create_rc(self, template):
97         k8s_utils.create_replication_controller(template)
98
99     def _delete_rcs(self):
100         for rc in self.template.rcs:
101             self._delete_rc(rc)
102
103     def _delete_rc(self, rc):
104         k8s_utils.delete_replication_controller(rc)
105
106     def _delete_pods(self):
107         for pod in self.template.pods:
108             self._delete_pod(pod)
109
110     def _delete_pod(self, pod):
111         k8s_utils.delete_pod(pod)
112
113     def _create_crd(self):
114         LOG.info('Create Custom Resource Definition elements')
115         for crd in self.template.crd:
116             crd.create()
117
118     def _delete_crd(self):
119         LOG.info('Delete Custom Resource Definition elements')
120         for crd in self.template.crd:
121             crd.delete()
122
123     def _create_networks(self):  # pragma: no cover
124         LOG.info('Create Network elements')
125         for net in self.template.network_objs:
126             net.create()
127
128     def _delete_networks(self):  # pragma: no cover
129         LOG.info('Create Network elements')
130         for net in self.template.network_objs:
131             net.delete()
132
133     def _get_key_path(self):
134         task_id = self.name.split('-')[-1]
135         k = 'files/yardstick_key-{}'.format(task_id)
136         return pkg_resources.resource_filename('yardstick.resources', k)
137
138     def _set_ssh_key(self):
139         rsa_key = paramiko.RSAKey.generate(bits=BITS_LENGTH)
140
141         LOG.info('Writing private key')
142         rsa_key.write_private_key_file(self.key_path)
143
144         LOG.info('Writing public key')
145         key = '{} {}\n'.format(rsa_key.get_name(), rsa_key.get_base64())
146         with open(self.public_key_path, 'w') as f:
147             f.write(key)
148
149         LOG.info('Create configmap for ssh key')
150         k8s_utils.create_config_map(self.ssh_key, {'authorized_keys': key})
151
152     def _delete_ssh_key(self):
153         k8s_utils.delete_config_map(self.ssh_key)
154         utils.remove_file(self.key_path)
155         utils.remove_file(self.public_key_path)
156
157     def _get_server(self, name):
158         service_name = '{}-service'.format(name)
159         service = k8s_utils.get_service_by_name(service_name).ports[0]
160
161         host = {
162             'name': service.name,
163             'ip': self._get_node_ip(),
164             'private_ip': k8s_utils.get_pod_by_name(name).status.pod_ip,
165             'ssh_port': service.node_port,
166             'user': 'root',
167             'key_filename': self.key_path,
168         }
169
170         return host
171
172     def _get_node_ip(self):
173         return k8s_utils.get_node_list().items[0].status.addresses[0].address
174
175     def _get_network(self, attr_name):
176         return None
177
178     def _get_physical_nodes(self):
179         return None
180
181     def _get_physical_node_for_server(self, server_name):
182         return None