kubernetes_utils: avoid 404 error code in delete_service()
[yardstick.git] / yardstick / orchestrator / kubernetes.py
index f690ab3..bf7aa9c 100644 (file)
@@ -22,6 +22,8 @@ class ContainerObject(object):
     SSH_MOUNT_PATH = '/tmp/.ssh/'
     IMAGE_DEFAULT = 'openretriever/yardstick'
     COMMAND_DEFAULT = '/bin/bash'
+    RESOURCES = ('requests', 'limits')
+    PORT_OPTIONS = ('containerPort', 'hostIP', 'hostPort', 'name', 'protocol')
 
     def __init__(self, name, ssh_key, **kwargs):
         self._name = name
@@ -32,6 +34,8 @@ class ContainerObject(object):
         self._volume_mounts = kwargs.get('volumeMounts', [])
         self._security_context = kwargs.get('securityContext')
         self._env = kwargs.get('env', [])
+        self._resources = kwargs.get('resources', {})
+        self._ports = kwargs.get('ports', [])
 
     def _create_volume_mounts(self):
         """Return all "volumeMounts" items per container"""
@@ -64,12 +68,28 @@ class ContainerObject(object):
             for env in self._env:
                 container['env'].append({'name': env['name'],
                                          'value': env['value']})
+        if self._ports:
+            container['ports'] = []
+            for port in self._ports:
+                if 'containerPort' not in port.keys():
+                    raise exceptions.KubernetesContainerPortNotDefined(
+                        port=port)
+                _port = {port_option: value for port_option, value
+                         in port.items() if port_option in self.PORT_OPTIONS}
+                container['ports'].append(_port)
+        if self._resources:
+            container['resources'] = {}
+            for res in (res for res in self._resources if
+                        res in self.RESOURCES):
+                container['resources'][res] = self._resources[res]
         return container
 
 
 class ReplicationControllerObject(object):
 
     SSHKEY_DEFAULT = 'yardstick_key'
+    RESTART_POLICY = ('Always', 'OnFailure', 'Never')
+    TOLERATIONS_KEYS = ('key', 'value', 'effect', 'operator')
 
     def __init__(self, name, **kwargs):
         super(ReplicationControllerObject, self).__init__()
@@ -80,6 +100,11 @@ class ReplicationControllerObject(object):
         self._volumes = parameters.pop('volumes', [])
         self._security_context = parameters.pop('securityContext', None)
         self._networks = parameters.pop('networks', [])
+        self._tolerations = parameters.pop('tolerations', [])
+        self._restart_policy = parameters.pop('restartPolicy', 'Always')
+        if self._restart_policy not in self.RESTART_POLICY:
+            raise exceptions.KubernetesWrongRestartPolicy(
+                rpolicy=self._restart_policy)
 
         containers = parameters.pop('containers', None)
         if containers:
@@ -105,7 +130,9 @@ class ReplicationControllerObject(object):
                     "spec": {
                         "containers": [],
                         "volumes": [],
-                        "nodeSelector": {}
+                        "nodeSelector": {},
+                        "restartPolicy": self._restart_policy,
+                        "tolerations": []
                     }
                 }
             }
@@ -117,6 +144,11 @@ class ReplicationControllerObject(object):
         self._add_volumes()
         self._add_security_context()
         self._add_networks()
+        self._add_tolerations()
+
+    @property
+    def networks(self):
+        return self._networks
 
     def get_template(self):
         return self.template
@@ -187,6 +219,18 @@ class ReplicationControllerObject(object):
                              'spec.template.metadata.annotations',
                              annotations)
 
+    def _add_tolerations(self):
+        tolerations = []
+        for tol in self._tolerations:
+            tolerations.append({k: tol[k] for k in tol
+                                if k in self.TOLERATIONS_KEYS})
+
+        tolerations = ([{'operator': 'Exists'}] if not tolerations
+                       else tolerations)
+        utils.set_dict_value(self.template,
+                             'spec.template.spec.tolerations',
+                             tolerations)
+
 
 class ServiceNodePortObject(object):
 
@@ -230,7 +274,7 @@ class ServiceNodePortObject(object):
         k8s_utils.create_service(self.template)
 
     def delete(self):
-        k8s_utils.delete_service(self._name)
+        k8s_utils.delete_service(self._name, skip_codes=[404])
 
 
 class CustomResourceDefinitionObject(object):
@@ -276,10 +320,10 @@ class CustomResourceDefinitionObject(object):
 
 class NetworkObject(object):
 
-    MANDATORY_PARAMETERS = {'name', 'plugin', 'args'}
+    MANDATORY_PARAMETERS = {'plugin', 'args'}
     KIND = 'Network'
 
-    def __init__(self, **kwargs):
+    def __init__(self, name, **kwargs):
         if not self.MANDATORY_PARAMETERS.issubset(kwargs):
             missing_parameters = ', '.join(
                 str(param) for param in
@@ -287,7 +331,7 @@ class NetworkObject(object):
             raise exceptions.KubernetesNetworkObjectDefinitionError(
                 missing_parameters=missing_parameters)
 
-        self._name = kwargs['name']
+        self._name = name
         self._plugin = kwargs['plugin']
         self._args = kwargs['args']
         self._crd = None
@@ -377,19 +421,20 @@ class KubernetesTemplate(object):
         context_cfg = copy.deepcopy(context_cfg)
         servers_cfg = context_cfg.pop('servers', {})
         crd_cfg = context_cfg.pop('custom_resources', [])
-        networks_cfg = context_cfg.pop('networks', [])
+        networks_cfg = context_cfg.pop('networks', {})
         self.name = name
         self.ssh_key = '{}-key'.format(name)
 
         self.rcs = {self._get_rc_name(rc): cfg
                     for rc, cfg in servers_cfg.items()}
-        self.k8s_objs = [ReplicationControllerObject(
+        self.rc_objs = [ReplicationControllerObject(
             rc, ssh_key=self.ssh_key, **cfg) for rc, cfg in self.rcs.items()]
         self.service_objs = [ServiceNodePortObject(rc, **cfg)
                              for rc, cfg in self.rcs.items()]
         self.crd = [CustomResourceDefinitionObject(self.name, **crd)
                     for crd in crd_cfg]
-        self.network_objs = [NetworkObject(**nobj) for nobj in networks_cfg]
+        self.network_objs = [NetworkObject(net_name, **net_data)
+                             for net_name, net_data in networks_cfg.items()]
         self.pods = []
 
     def _get_rc_name(self, rc_name):
@@ -401,3 +446,8 @@ class KubernetesTemplate(object):
                      if p.metadata.name.startswith(s)]
 
         return self.pods
+
+    def get_rc_by_name(self, rc_name):
+        """Returns a ``ReplicationControllerObject``, searching by name"""
+        for rc in (rc for rc in self.rc_objs if rc.name == rc_name):
+            return rc