1 ##############################################################################
2 # Copyright (c) 2017 Huawei Technologies Co.,Ltd.
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 ##############################################################################
12 from yardstick.common import constants
13 from yardstick.common import exceptions
14 from yardstick.common import utils
15 from yardstick.common import kubernetes_utils as k8s_utils
18 class ContainerObject(object):
20 SSH_MOUNT_PATH = '/tmp/.ssh/'
21 IMAGE_DEFAULT = 'openretriever/yardstick'
22 COMMAND_DEFAULT = '/bin/bash'
24 def __init__(self, name, ssh_key, **kwargs):
26 self._ssh_key = ssh_key
27 self._image = kwargs.get('image', self.IMAGE_DEFAULT)
28 self._command = [kwargs.get('command', self.COMMAND_DEFAULT)]
29 self._args = kwargs.get('args', [])
30 self._volume_mounts = kwargs.get('volumeMounts', [])
31 self._security_context = kwargs.get('securityContext')
33 def _create_volume_mounts(self):
34 """Return all "volumeMounts" items per container"""
35 volume_mounts_items = [self._create_volume_mounts_item(vol)
36 for vol in self._volume_mounts]
37 ssh_vol = {'name': self._ssh_key,
38 'mountPath': self.SSH_MOUNT_PATH}
39 volume_mounts_items.append(self._create_volume_mounts_item(ssh_vol))
40 return volume_mounts_items
43 def _create_volume_mounts_item(volume_mount):
44 """Create a "volumeMounts" item"""
45 return {'name': volume_mount['name'],
46 'mountPath': volume_mount['mountPath'],
47 'readOnly': volume_mount.get('readOnly', False)}
49 def get_container_item(self):
50 """Create a "container" item"""
51 container_name = '{}-container'.format(self._name)
52 container = {'args': self._args,
53 'command': self._command,
55 'name': container_name,
56 'volumeMounts': self._create_volume_mounts()}
57 if self._security_context:
58 container['securityContext'] = self._security_context
62 class KubernetesObject(object):
64 SSHKEY_DEFAULT = 'yardstick_key'
66 def __init__(self, name, **kwargs):
67 super(KubernetesObject, self).__init__()
68 parameters = copy.deepcopy(kwargs)
70 self.node_selector = parameters.pop('nodeSelector', {})
71 self.ssh_key = parameters.pop('ssh_key', self.SSHKEY_DEFAULT)
72 self._volumes = parameters.pop('volumes', [])
73 self._security_context = parameters.pop('securityContext', None)
75 containers = parameters.pop('containers', None)
78 ContainerObject(self.name, self.ssh_key, **container)
79 for container in containers]
82 ContainerObject(self.name, self.ssh_key, **parameters)]
86 "kind": "ReplicationController",
107 self._change_value_according_name(name)
108 self._add_containers()
109 self._add_node_selector()
111 self._add_security_context()
113 def get_template(self):
116 def _change_value_according_name(self, name):
117 utils.set_dict_value(self.template, 'metadata.name', name)
119 utils.set_dict_value(self.template,
120 'spec.template.metadata.labels.app',
123 def _add_containers(self):
124 containers = [container.get_container_item()
125 for container in self._containers]
126 utils.set_dict_value(self.template,
127 'spec.template.spec.containers',
130 def _add_node_selector(self):
131 utils.set_dict_value(self.template,
132 'spec.template.spec.nodeSelector',
135 def _add_volumes(self):
136 """Add "volume" items to container specs, including the SSH one"""
137 volume_items = [self._create_volume_item(vol) for vol in self._volumes]
138 volume_items.append(self._create_ssh_key_volume())
139 utils.set_dict_value(self.template,
140 'spec.template.spec.volumes',
143 def _create_ssh_key_volume(self):
144 """Create a "volume" item of type "configMap" for the SSH key"""
145 return {'name': self.ssh_key,
146 'configMap': {'name': self.ssh_key}}
149 def _create_volume_item(volume):
150 """Create a "volume" item"""
151 volume = copy.deepcopy(volume)
152 name = volume.pop('name')
153 for key in (k for k in volume if k in k8s_utils.get_volume_types()):
155 type_data = volume[key]
158 raise exceptions.KubernetesTemplateInvalidVolumeType(volume=volume)
160 return {'name': name,
161 type_name: type_data}
163 def _add_security_context(self):
164 if self._security_context:
165 utils.set_dict_value(self.template,
166 'spec.template.spec.securityContext',
167 self._security_context)
170 class ServiceObject(object):
172 def __init__(self, name):
173 self.name = '{}-service'.format(name)
176 'name': '{}-service'.format(name)
193 k8s_utils.create_service(self.template)
196 k8s_utils.delete_service(self.name)
199 class CustomResourceDefinitionObject(object):
201 MANDATORY_PARAMETERS = {'name'}
203 def __init__(self, ctx_name, **kwargs):
204 if not self.MANDATORY_PARAMETERS.issubset(kwargs):
205 missing_parameters = ', '.join(
206 str(param) for param in
207 (self.MANDATORY_PARAMETERS - set(kwargs)))
208 raise exceptions.KubernetesCRDObjectDefinitionError(
209 missing_parameters=missing_parameters)
211 singular = kwargs['name']
212 plural = singular + 's'
213 kind = singular.title()
214 version = kwargs.get('version', 'v1')
215 scope = kwargs.get('scope', constants.SCOPE_NAMESPACED)
216 group = ctx_name + '.com'
217 self._name = metadata_name = plural + '.' + group
221 'name': metadata_name
227 'names': {'plural': plural,
228 'singular': singular,
234 k8s_utils.create_custom_resource_definition(self._template)
237 k8s_utils.delete_custom_resource_definition(self._name)
240 class KubernetesTemplate(object):
242 def __init__(self, name, context_cfg):
243 """KubernetesTemplate object initialization
245 :param name: (str) name of the Kubernetes context
246 :param context_cfg: (dict) context definition
248 context_cfg = copy.deepcopy(context_cfg)
249 servers_cfg = context_cfg.pop('servers', {})
250 crd_cfg = context_cfg.pop('custom_resources', [])
252 self.ssh_key = '{}-key'.format(name)
254 self.rcs = [self._get_rc_name(rc) for rc in servers_cfg]
255 self.k8s_objs = [KubernetesObject(self._get_rc_name(rc),
256 ssh_key=self.ssh_key,
258 for rc, cfg in servers_cfg.items()]
259 self.service_objs = [ServiceObject(s) for s in self.rcs]
260 self.crd = [CustomResourceDefinitionObject(self.name, **crd)
265 def _get_rc_name(self, rc_name):
266 return '{}-{}'.format(rc_name, self.name)
268 def get_rc_pods(self):
269 resp = k8s_utils.get_pod_list()
270 self.pods = [p.metadata.name for p in resp.items for s in self.rcs
271 if p.metadata.name.startswith(s)]