Merge "Kubernetes (k8s) support"
[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.kubernetes import KubernetesTemplate
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.name = ''
33         self.ssh_key = ''
34         self.key_path = ''
35         self.public_key_path = ''
36         self.template = None
37
38         super(KubernetesContext, self).__init__()
39
40     def init(self, attrs):
41         self.name = attrs.get('name', '')
42
43         template_cfg = attrs.get('servers', {})
44         self.template = KubernetesTemplate(self.name, template_cfg)
45
46         self.ssh_key = '{}-key'.format(self.name)
47
48         self.key_path = self._get_key_path()
49         self.public_key_path = '{}.pub'.format(self.key_path)
50
51     def deploy(self):
52         LOG.info('Creating ssh key')
53         self._set_ssh_key()
54
55         LOG.info('Launch containers')
56         self._create_rcs()
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
67         super(KubernetesContext, self).undeploy()
68
69     def _wait_until_running(self):
70         while not all(self._check_pod_status(p) for p in self.template.pods):
71             time.sleep(1)
72
73     def _check_pod_status(self, pod):
74         status = k8s_utils.read_pod_status(pod)
75         LOG.debug('%s:%s', pod, status)
76         if status == 'Failed':
77             LOG.error('Pod %s status is failed', pod)
78             raise RuntimeError
79         if status != 'Running':
80             return False
81         return True
82
83     def _create_rcs(self):
84         for obj in self.template.k8s_objs:
85             self._create_rc(obj.get_template())
86
87     def _create_rc(self, template):
88         k8s_utils.create_replication_controller(template)
89
90     def _delete_rcs(self):
91         for rc in self.template.rcs:
92             self._delete_rc(rc)
93
94     def _delete_rc(self, rc):
95         k8s_utils.delete_replication_controller(rc)
96
97     def _delete_pods(self):
98         for pod in self.template.pods:
99             self._delete_pod(pod)
100
101     def _delete_pod(self, pod):
102         k8s_utils.delete_pod(pod)
103
104     def _get_key_path(self):
105         task_id = self.name.split('-')[-1]
106         k = 'files/yardstick_key-{}'.format(task_id)
107         return pkg_resources.resource_filename('yardstick.resources', k)
108
109     def _set_ssh_key(self):
110         rsa_key = paramiko.RSAKey.generate(bits=BITS_LENGTH)
111
112         LOG.info('Writing private key')
113         rsa_key.write_private_key_file(self.key_path)
114
115         LOG.info('Writing public key')
116         key = '{} {}\n'.format(rsa_key.get_name(), rsa_key.get_base64())
117         with open(self.public_key_path, 'w') as f:
118             f.write(key)
119
120         LOG.info('Create configmap for ssh key')
121         k8s_utils.create_config_map(self.ssh_key, {'authorized_keys': key})
122
123     def _delete_ssh_key(self):
124         k8s_utils.delete_config_map(self.ssh_key)
125         utils.remove_file(self.key_path)
126         utils.remove_file(self.public_key_path)
127
128     def _get_server(self, name):
129         resp = k8s_utils.get_pod_list()
130         hosts = ({'name': n.metadata.name,
131                   'ip': n.status.pod_ip,
132                   'user': 'root',
133                   'key_filename': self.key_path,
134                   'private_ip': n.status.pod_ip}
135                  for n in resp.items if n.metadata.name.startswith(name))
136
137         return next(hosts, None)