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