Added 'k8s_deployed' fixture

Created a separate fixture for Kubernetes deployment.
Modified existing k8s related fixtures / tests so they
use it now and updated templates with k8s environments.

Also this patch includes few minor changes:

 * removed unused fixture 'deploy_openstack' which
   was a full copy of 'openstack_deployed' fixture;
 * removed unused modules imports;
 * fixed typos and docstrings.

Change-Id: Ic35551f3e52913cede753b92e7d5a81f54570b01
Reviewed-on: https://review.gerrithub.io/365234
Reviewed-by: <vrovachev@mirantis.com>
Reviewed-by: Dennis Dmitriev <dis.xcom@gmail.com>
Tested-by: Tatyanka Leontovich <tleontovich@mirantis.com>
diff --git a/tcp_tests/managers/k8s/__init__.py b/tcp_tests/managers/k8s/__init__.py
new file mode 100644
index 0000000..bd76aa7
--- /dev/null
+++ b/tcp_tests/managers/k8s/__init__.py
@@ -0,0 +1,20 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+import urllib3
+
+from tcp_tests.managers.k8s.cluster import K8sCluster
+
+__all__ = ['K8sCluster']
+
+urllib3.disable_warnings()  # Supress https insecure warning
diff --git a/tcp_tests/managers/k8s/base.py b/tcp_tests/managers/k8s/base.py
new file mode 100644
index 0000000..7adb41a
--- /dev/null
+++ b/tcp_tests/managers/k8s/base.py
@@ -0,0 +1,108 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+class K8sBaseResource(object):
+    """docstring for K8sBaseResource"""
+
+    def __init__(self, manager, data):
+        self._manager = manager
+        self._add_details(data)
+
+    def __repr__(self):
+        reprkeys = sorted(k
+                          for k in self.__dict__.keys()
+                          if k[0] != '_' and
+                          k not in ['manager'])
+        info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys)
+        return "<%s %s>" % (self.__class__.__name__, info)
+
+    @property
+    def api_version(self):
+        return self._data.api_version
+
+    def _add_details(self, data):
+        self._data = data
+        for k in [k for k in dir(data)
+                  if not any((k.startswith('_'), k in ('to_dict', 'to_str')))]:
+            try:
+                setattr(self, k, getattr(data, k))
+            except AttributeError:
+                # In this case we already defined the attribute on the class
+                pass
+
+    def __eq__(self, other):
+        if not isinstance(other, K8sBaseResource):
+            return NotImplemented
+        # two resources of different types are not equal
+        if not isinstance(other, self.__class__):
+            return False
+        return self._info == other._info
+
+
+class K8sBaseManager(object):
+
+    resource_class = None
+
+    def __init__(self, api, namespace):
+        self._api = api
+        self._namespace = namespace
+        self._raw = None
+
+    @property
+    def api(self):
+        return self._api
+
+    @property
+    def namespace(self):
+        return self._namespace
+
+    def get(self, *args, **kwargs):
+        if not hasattr(self, '_get'):
+            raise NotImplementedError(
+                '{} does not have {}'.format(self, '_get'))
+
+        return self.resource_class(self, self._get(*args, **kwargs))
+
+    def list(self, *args, **kwargs):
+        if not hasattr(self, '_list'):
+            raise NotImplementedError(
+                '{} does not have {}'.format(self, '_list'))
+
+        lst = self._list(*args, **kwargs)
+
+        return [self.resource_class(self, item) for item in lst.items]
+
+    def create(self, *args, **kwargs):
+        if not hasattr(self, '_create'):
+            raise NotImplementedError(
+                '{} does not have {}'.format(self, '_create'))
+        return self.resource_class(self, self._create(*args, **kwargs))
+
+    def replace(self, *args, **kwargs):
+        if not hasattr(self, '_replace'):
+            raise NotImplementedError(
+                '{} does not have {}'.format(self, '_replace'))
+        return self._replace(*args, **kwargs)
+
+    def delete(self, *args, **kwargs):
+        if not hasattr(self, '_delete'):
+            raise NotImplementedError(
+                '{} does not have {}'.format(self, '_delete'))
+        return self._delete(*args, **kwargs)
+
+    def deletecollection(self, *args, **kwargs):
+        if not hasattr(self, '_deletecollection'):
+            raise NotImplementedError(
+                '{} does not have {}'.format(self, '_deletecollection'))
+        return self._deletecollection(*args, **kwargs)
diff --git a/tcp_tests/managers/k8s/cluster.py b/tcp_tests/managers/k8s/cluster.py
new file mode 100644
index 0000000..424ab32
--- /dev/null
+++ b/tcp_tests/managers/k8s/cluster.py
@@ -0,0 +1,110 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+import base64
+import ssl
+
+from k8sclient.client import api_client
+from k8sclient.client.apis import apiv_api
+from k8sclient.client.apis import apisextensionsvbeta_api
+from k8sclient.client.apis import apisbatchv_api
+
+from tcp_tests.managers.k8s.componentstatuses import \
+    K8sComponentStatusManager
+from tcp_tests.managers.k8s.daemonsets import K8sDaemonSetManager
+from tcp_tests.managers.k8s.deployments import K8sDeploymentManager
+from tcp_tests.managers.k8s.endpoints import K8sEndpointManager
+from tcp_tests.managers.k8s.events import K8sEventManager
+from tcp_tests.managers.k8s.horizontalpodautoscalers import \
+    K8sHorizontalPodAutoscalerManager
+from tcp_tests.managers.k8s.ingresses import K8sIngressManager
+from tcp_tests.managers.k8s.jobs import K8sJobManager
+from tcp_tests.managers.k8s.limitranges import K8sLimitRangeManager
+from tcp_tests.managers.k8s.namespaces import K8sNamespaceManager
+from tcp_tests.managers.k8s.nodes import K8sNodeManager
+from tcp_tests.managers.k8s.persistentvolumeclaims import \
+    K8sPersistentVolumeClaimManager
+from tcp_tests.managers.k8s.persistentvolumes import \
+    K8sPersistentVolumeManager
+from tcp_tests.managers.k8s.pods import K8sPodManager
+from tcp_tests.managers.k8s.replicationcontrollers import \
+    K8sReplicationControllerManager
+from tcp_tests.managers.k8s.resourcequotas import K8sResourceQuotaManager
+from tcp_tests.managers.k8s.secrets import K8sSecretManager
+from tcp_tests.managers.k8s.serviceaccounts import \
+    K8sServiceAccountManager
+from tcp_tests.managers.k8s.services import K8sServiceManager
+from tcp_tests.managers.k8s.replicasets import K8sReplicaSetManager
+
+
+class K8sCluster(object):
+    """docstring for K8sCluster"""
+
+    def __init__(self, schema="https", user=None, password=None,
+                 host='localhost', port='443', default_namespace='default'):
+        if user and password:
+            auth_string = '%s:%s' % (user, password)
+            auth = base64.encodestring(auth_string.encode()).decode()[:-1]
+            auth = "Basic {}".format(auth)
+            self._client = api_client.ApiClient(
+                '{schema}://{host}:{port}/'.format(
+                    schema=schema, host=host, port=port))
+            self._client.set_default_header('Authorization', auth)
+            restcli_impl = self._client.RESTClient.IMPL
+            restcli_impl.ssl_pool_manager.connection_pool_kw['cert_reqs'] = \
+                ssl.CERT_NONE
+
+        else:
+            self._client = api_client.ApiClient(
+                '{schema}://{host}:{port}/'.format(
+                    schema=schema, host=host, port=port))
+        self._api = apiv_api.ApivApi(self._client)
+        self._bapi = apisbatchv_api.ApisbatchvApi(self._client)
+        self._eapi = apisextensionsvbeta_api.ApisextensionsvbetaApi(
+            self._client)
+        self._default_namespace = default_namespace
+
+        self.nodes = K8sNodeManager(self._api, self._default_namespace)
+        self.pods = K8sPodManager(self._api, self._default_namespace)
+        self.endpoints = K8sEndpointManager(self._api, self._default_namespace)
+        self.namespaces = K8sNamespaceManager(self._api,
+                                              self._default_namespace)
+        self.services = K8sServiceManager(self._api, self._default_namespace)
+        self.serviceaccounts = K8sServiceAccountManager(
+            self._api, self._default_namespace)
+        self.secrets = K8sSecretManager(self._api, self._default_namespace)
+        self.events = K8sEventManager(self._api, self._default_namespace)
+        self.limitranges = K8sLimitRangeManager(self._api,
+                                                self._default_namespace)
+        self.jobs = K8sJobManager(self._bapi, self._default_namespace)
+        self.daemonsets = K8sDaemonSetManager(self._eapi,
+                                              self._default_namespace)
+        self.ingresses = K8sIngressManager(self._eapi, self._default_namespace)
+        self.deployments = K8sDeploymentManager(self._eapi,
+                                                self._default_namespace)
+        self.horizontalpodautoscalers = K8sHorizontalPodAutoscalerManager(
+            self._eapi, self._default_namespace)
+        self.componentstatuses = K8sComponentStatusManager(
+            self._api, self._default_namespace)
+        self.resourcequotas = K8sResourceQuotaManager(
+            self._api, self._default_namespace)
+        self.replicationcontrollers = K8sReplicationControllerManager(
+            self._api, self._default_namespace)
+        self.pvolumeclaims = K8sPersistentVolumeClaimManager(
+            self._api, self._default_namespace)
+        self.pvolumes = K8sPersistentVolumeManager(
+            self._api, self._default_namespace)
+        self.replicasets = K8sReplicaSetManager(
+            self._eapi, self._default_namespace
+        )
diff --git a/tcp_tests/managers/k8s/componentstatuses.py b/tcp_tests/managers/k8s/componentstatuses.py
new file mode 100644
index 0000000..a991576
--- /dev/null
+++ b/tcp_tests/managers/k8s/componentstatuses.py
@@ -0,0 +1,39 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sComponentStatus(K8sBaseResource):
+    """docstring for K8sComponentStatus"""
+
+    def __repr__(self):
+        return "<K8sComponentStatus: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sComponentStatusManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sComponentStatus
+
+    def _get(self, name, **kwargs):
+        return self.api.read_namespaced_component_status(name=name, **kwargs)
+
+    def _list(self, **kwargs):
+        return self.api.list_namespaced_component_status(**kwargs)
diff --git a/tcp_tests/managers/k8s/daemonsets.py b/tcp_tests/managers/k8s/daemonsets.py
new file mode 100644
index 0000000..dc2c5f7
--- /dev/null
+++ b/tcp_tests/managers/k8s/daemonsets.py
@@ -0,0 +1,79 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sDaemonSet(K8sBaseResource):
+    """docstring for K8sDaemonSet"""
+
+    def __repr__(self):
+        return "<K8sDaemonSet: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+    @property
+    def namespace(self):
+        return self.metadata.namespace
+
+
+class K8sDaemonSetManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sDaemonSet
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_daemon_set(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_daemon_set(
+            namespace=namespace, **kwargs)
+
+    def _full_list(self, **kwargs):
+        return self.api.list_daemon_set(**kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_daemon_set(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_daemon_set(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_daemon_set(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_daemon_set(
+            namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
+
+    def update(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.patch_namespaced_daemon_set(
+            body=body, name=name, namespace=namespace, **kwargs)
diff --git a/tcp_tests/managers/k8s/deployments.py b/tcp_tests/managers/k8s/deployments.py
new file mode 100644
index 0000000..1dbd1d2
--- /dev/null
+++ b/tcp_tests/managers/k8s/deployments.py
@@ -0,0 +1,70 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sDeployment(K8sBaseResource):
+    """docstring for K8sDeployment"""
+
+    def __repr__(self):
+        return "<K8sDeployment: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sDeploymentManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sDeployment
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_deployment(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_deployment(
+            namespace=namespace, **kwargs)
+
+    def _full_list(self, **kwargs):
+        return self.api.list_deployment(**kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_deployment(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_deployment(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_deployment(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_deployment(
+            namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
diff --git a/tcp_tests/managers/k8s/endpoints.py b/tcp_tests/managers/k8s/endpoints.py
new file mode 100644
index 0000000..ed1066e
--- /dev/null
+++ b/tcp_tests/managers/k8s/endpoints.py
@@ -0,0 +1,70 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sEndpoint(K8sBaseResource):
+    """docstring for K8sEndpoint"""
+
+    def __repr__(self):
+        return "<K8sEndpoint: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sEndpointManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sEndpoint
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_endpoints(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_endpoints(
+            namespace=namespace, **kwargs)
+
+    def _full_list(self, **kwargs):
+        return self.api.list_endpoints(**kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_endpoints(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_endpoints(
+            body=body, name=body, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_endpoints(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_endpoints(
+            namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
diff --git a/tcp_tests/managers/k8s/events.py b/tcp_tests/managers/k8s/events.py
new file mode 100644
index 0000000..099e9e4
--- /dev/null
+++ b/tcp_tests/managers/k8s/events.py
@@ -0,0 +1,69 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sEvent(K8sBaseResource):
+    """docstring for K8sEvent"""
+
+    def __repr__(self):
+        return "<K8sEvent: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sEventManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sEvent
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_event(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_event(namespace=namespace, **kwargs)
+
+    def _full_list(self, **kwargs):
+        return self.api.list_event(**kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_event(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_event(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_event(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_event(
+            namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
diff --git a/tcp_tests/managers/k8s/horizontalpodautoscalers.py b/tcp_tests/managers/k8s/horizontalpodautoscalers.py
new file mode 100644
index 0000000..6ce78e7
--- /dev/null
+++ b/tcp_tests/managers/k8s/horizontalpodautoscalers.py
@@ -0,0 +1,70 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sHorizontalPodAutoscaler(K8sBaseResource):
+    """docstring for K8sHorizontalPodAutoscaler"""
+
+    def __repr__(self):
+        return "<K8sHorizontalPodAutoscaler: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sHorizontalPodAutoscalerManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sHorizontalPodAutoscaler
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_horizontal_pod_autoscaler(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_horizontal_pod_autoscaler(
+            namespace=namespace, **kwargs)
+
+    def _full_list(self, **kwargs):
+        return self.api.list_horizontal_pod_autoscaler(**kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_horizontal_pod_autoscaler(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_horizontal_pod_autoscaler(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_horizontal_pod_autoscaler(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_horizontal_pod_autoscaler(
+            namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
diff --git a/tcp_tests/managers/k8s/ingresses.py b/tcp_tests/managers/k8s/ingresses.py
new file mode 100644
index 0000000..81b240e
--- /dev/null
+++ b/tcp_tests/managers/k8s/ingresses.py
@@ -0,0 +1,70 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sIngress(K8sBaseResource):
+    """docstring for K8sIngress"""
+
+    def __repr__(self):
+        return "<K8sIngress: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sIngressManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sIngress
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_ingress(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_ingress(
+            namespace=namespace, **kwargs)
+
+    def _full_list(self, **kwargs):
+        return self.api.list_ingress(**kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_ingress(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_ingress(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_ingress(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_ingress(
+            namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
diff --git a/tcp_tests/managers/k8s/jobs.py b/tcp_tests/managers/k8s/jobs.py
new file mode 100644
index 0000000..a2dbb81
--- /dev/null
+++ b/tcp_tests/managers/k8s/jobs.py
@@ -0,0 +1,69 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sJob(K8sBaseResource):
+    """docstring for K8sJob"""
+
+    def __repr__(self):
+        return "<K8sJob: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sJobManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sJob
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_job(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_job(namespace=namespace, **kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_job(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_job(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_job(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_job(
+            namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
+
+    def _full_list(self, **kwargs):
+        return self.api.list_job(**kwargs)
diff --git a/tcp_tests/managers/k8s/limitranges.py b/tcp_tests/managers/k8s/limitranges.py
new file mode 100644
index 0000000..7136300
--- /dev/null
+++ b/tcp_tests/managers/k8s/limitranges.py
@@ -0,0 +1,63 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sLimitRange(K8sBaseResource):
+    """docstring for K8sLimitRange"""
+
+    def __repr__(self):
+        return "<K8sLimitRange: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sLimitRangeManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sLimitRange
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_limit_range(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_limit_range(
+            namespace=namespace, **kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_limit_range(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_limit_range(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_limit_range(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_limit_range(
+            namespace=namespace, **kwargs)
diff --git a/tcp_tests/managers/k8s/namespaces.py b/tcp_tests/managers/k8s/namespaces.py
new file mode 100644
index 0000000..8c36302
--- /dev/null
+++ b/tcp_tests/managers/k8s/namespaces.py
@@ -0,0 +1,51 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sNamespace(K8sBaseResource):
+    """docstring for ClassName"""
+
+    def __repr__(self):
+        return "<K8sNamespace: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sNamespaceManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sNamespace
+
+    def _get(self, name, **kwargs):
+        return self.api.read_namespaced_namespace(name, **kwargs)
+
+    def _list(self, **kwargs):
+        return self.api.list_namespaced_namespace(**kwargs)
+
+    def _create(self, body, **kwargs):
+        return self.api.create_namespaced_namespace(body, **kwargs)
+
+    def _replace(self, body, name, **kwargs):
+        return self.api.replace_namespaced_namespace(body, name, **kwargs)
+
+    def _delete(self, body, name, **kwargs):
+        return self.api.delete_namespaced_namespace(body, name, **kwargs)
+
+    def _deletecollection(self, **kwargs):
+        return self.api.deletecollection_namespaced_namespace(**kwargs)
diff --git a/tcp_tests/managers/k8s/nodes.py b/tcp_tests/managers/k8s/nodes.py
new file mode 100644
index 0000000..c6d4dbe
--- /dev/null
+++ b/tcp_tests/managers/k8s/nodes.py
@@ -0,0 +1,81 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sNode(K8sBaseResource):
+    """docstring for ClassName"""
+
+    def __repr__(self):
+        return "<K8sNode: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+    @property
+    def labels(self):
+        return self.metadata.labels
+
+    @labels.setter
+    def labels(self, labels):
+        current_labels = {
+            label: None for label in self.labels
+        }
+        current_labels.update(labels)
+        self.add_labels(labels=current_labels)
+
+    def add_labels(self, labels):
+        if not isinstance(labels, dict):
+            raise TypeError("labels must be a dict!")
+        body = {
+            "metadata":
+            {
+                "labels": labels
+            }
+        }
+        self._add_details(self._manager.update(body=body, name=self.name))
+
+    def remove_labels(self, list_labels):
+        labels = {label: None for label in list_labels}
+        self.add_labels(labels=labels)
+
+
+class K8sNodeManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sNode
+
+    def _get(self, name, **kwargs):
+        return self.api.read_namespaced_node(name=name, **kwargs)
+
+    def _list(self, **kwargs):
+        return self.api.list_namespaced_node(**kwargs)
+
+    def _create(self, body, **kwargs):
+        return self.api.create_namespaced_node(body=body, **kwargs)
+
+    def _replace(self, body, name, **kwargs):
+        return self.api.replace_namespaced_node(body=body, name=name, **kwargs)
+
+    def _delete(self, body, name, **kwargs):
+        return self.api.delete_namespaced_node(body=body, name=name, **kwargs)
+
+    def _deletecollection(self, **kwargs):
+        return self.api.deletecollection_namespaced_node(**kwargs)
+
+    def update(self, body, name, **kwargs):
+        return self.api.patch_namespaced_node(body=body, name=name, **kwargs)
diff --git a/tcp_tests/managers/k8s/persistentvolumeclaims.py b/tcp_tests/managers/k8s/persistentvolumeclaims.py
new file mode 100644
index 0000000..f28f622
--- /dev/null
+++ b/tcp_tests/managers/k8s/persistentvolumeclaims.py
@@ -0,0 +1,63 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sPersistentVolumeClaim(K8sBaseResource):
+    """docstring for K8sPersistentVolumeClaim"""
+
+    def __repr__(self):
+        return "<K8sPersistentVolumeClaim: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sPersistentVolumeClaimManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sPersistentVolumeClaim
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_persistent_volume_claim(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_persistent_volume_claim(
+            namespace=namespace, **kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_persistent_volume_claim(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_persistent_volume_claim(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_persistent_volume_claim(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_persistent_volume_claim(
+            namespace=namespace, **kwargs)
diff --git a/tcp_tests/managers/k8s/persistentvolumes.py b/tcp_tests/managers/k8s/persistentvolumes.py
new file mode 100644
index 0000000..8ab7ec2
--- /dev/null
+++ b/tcp_tests/managers/k8s/persistentvolumes.py
@@ -0,0 +1,57 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sPersistentVolume(K8sBaseResource):
+    """docstring for K8sPersistentVolume"""
+
+    def __repr__(self):
+        return "<K8sPersistentVolume: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sPersistentVolumeManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sPersistentVolume
+
+    def _get(self, name, **kwargs):
+        return self.api.read_namespaced_persistent_volume(
+            name=name, **kwargs)
+
+    def _list(self, **kwargs):
+        return self.api.list_namespaced_persistent_volume(
+            **kwargs)
+
+    def _create(self, body, **kwargs):
+        return self.api.create_namespaced_persistent_volume(
+            body, **kwargs)
+
+    def _replace(self, body, name, **kwargs):
+        return self.api.replace_namespaced_persistent_volume(
+            body=body, name=name, **kwargs)
+
+    def _delete(self, body, name, **kwargs):
+        return self.api.delete_namespaced_persistent_volume(
+            body=body, name=name, **kwargs)
+
+    def _deletecollection(self, **kwargs):
+        return self.api.deletecollection_namespaced_persistent_volume(
+            **kwargs)
diff --git a/tcp_tests/managers/k8s/pods.py b/tcp_tests/managers/k8s/pods.py
new file mode 100644
index 0000000..94abc20
--- /dev/null
+++ b/tcp_tests/managers/k8s/pods.py
@@ -0,0 +1,108 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+from devops.helpers import helpers
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sPod(K8sBaseResource):
+    """docstring for K8sPod"""
+
+    def __repr__(self):
+        return "<K8sPod: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+    @property
+    def phase(self):
+        return self.status.phase
+
+    @property
+    def namespace(self):
+        return self.metadata.namespace
+
+    def wait_phase(self, phase, timeout=60, interval=5):
+        """Wait phase of pod_name from namespace while timeout
+
+        :param list or str: phase
+        :param int: timeout
+
+        :rtype: None
+        """
+        if isinstance(phase, str):
+            phase = [phase]
+
+        def check():
+            self._add_details(self._manager.get(name=self.name,
+                                                namespace=self.namespace))
+            return self.phase in phase
+
+        helpers.wait(check, timeout=timeout, interval=interval,
+                     timeout_msg='Timeout waiting({timeout}s), pod {pod_name} '
+                                 'is not in "{phase}" phase'.format(
+                                     timeout=timeout,
+                                     pod_name=self.name,
+                                     phase=phase))
+
+    def wait_running(self, timeout=60, interval=5):
+        self.wait_phase(['Running'], timeout=timeout, interval=interval)
+
+
+class K8sPodManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sPod
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_pod(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_pod(namespace=namespace, **kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_pod(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_pod(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        # NOTE: the following two lines should be deleted after
+        # serialization is fixed in python-k8sclient
+        if isinstance(body, self.resource_class):
+            body = body.swagger_types
+        return self.api.delete_namespaced_pod(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_pod(
+            namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
+
+    def _full_list(self, **kwargs):
+        return self.api.list_pod(**kwargs)
diff --git a/tcp_tests/managers/k8s/replicasets.py b/tcp_tests/managers/k8s/replicasets.py
new file mode 100644
index 0000000..31b6db6
--- /dev/null
+++ b/tcp_tests/managers/k8s/replicasets.py
@@ -0,0 +1,70 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sReplicaSet(K8sBaseResource):
+    """docstring for K8sPod"""
+
+    def __repr__(self):
+        return "<K8sPod: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sReplicaSetManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sReplicaSet
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_replica_set(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_replica_set(namespace=namespace,
+                                                    **kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_replica_set(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_replica_set(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_replica_set(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_replica_set(
+            namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
+
+    def _full_list(self, **kwargs):
+        return self.api.list_replica_set(**kwargs)
diff --git a/tcp_tests/managers/k8s/replicationcontrollers.py b/tcp_tests/managers/k8s/replicationcontrollers.py
new file mode 100644
index 0000000..6cf7da4
--- /dev/null
+++ b/tcp_tests/managers/k8s/replicationcontrollers.py
@@ -0,0 +1,70 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sReplicationController(K8sBaseResource):
+    """docstring for K8sReplicationController"""
+
+    def __repr__(self):
+        return "<K8sReplicationController: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sReplicationControllerManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sReplicationController
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_replication_controller(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_replication_controller(
+            namespace=namespace, **kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_replication_controller(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_replication_controller(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_replication_controller(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_replication_controller(
+            namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
+
+    def _full_list(self, **kwargs):
+        return self.api.list_replication_controller(**kwargs)
diff --git a/tcp_tests/managers/k8s/resourcequotas.py b/tcp_tests/managers/k8s/resourcequotas.py
new file mode 100644
index 0000000..49d81d5
--- /dev/null
+++ b/tcp_tests/managers/k8s/resourcequotas.py
@@ -0,0 +1,70 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sResourceQuota(K8sBaseResource):
+    """docstring for K8sResourceQuota"""
+
+    def __repr__(self):
+        return "<K8sResourceQuota: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sResourceQuotaManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sResourceQuota
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_resource_quota(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_resource_quota(
+            namespace=namespace, **kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_resource_quota(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_resource_quota(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_resource_quota(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_resource_quota(
+            namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
+
+    def _full_list(self, **kwargs):
+        return self.api.list_resourse_quota(**kwargs)
diff --git a/tcp_tests/managers/k8s/secrets.py b/tcp_tests/managers/k8s/secrets.py
new file mode 100644
index 0000000..355c884
--- /dev/null
+++ b/tcp_tests/managers/k8s/secrets.py
@@ -0,0 +1,70 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sSecret(K8sBaseResource):
+    """docstring for K8sSecret"""
+
+    def __repr__(self):
+        return "<K8sSecret: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sSecretManager(K8sBaseManager):
+    """docstring for ClassName"""
+
+    resource_class = K8sSecret
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_secret(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_secret(
+            namespace=namespace, **kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_secret(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_secret(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_secret(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_secret(
+            namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
+
+    def _full_list(self, **kwargs):
+        return self.api.list_secret(**kwargs)
diff --git a/tcp_tests/managers/k8s/serviceaccounts.py b/tcp_tests/managers/k8s/serviceaccounts.py
new file mode 100644
index 0000000..bf58b4c
--- /dev/null
+++ b/tcp_tests/managers/k8s/serviceaccounts.py
@@ -0,0 +1,70 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sServiceAccount(K8sBaseResource):
+    """docstring for K8sServiceAccount"""
+
+    def __repr__(self):
+        return "<K8sServiceAccount: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+
+class K8sServiceAccountManager(K8sBaseManager):
+    """docstring for K8sServiceAccountManager"""
+
+    resource_class = K8sServiceAccount
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_service_account(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_service_account(
+            namespace=namespace, **kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_service_account(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_service_account(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_service_account(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _deletecollection(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.deletecollection_namespaced_service_account(
+            namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
+
+    def _full_list(self, **kwargs):
+        return self.api.list_service_account(**kwargs)
diff --git a/tcp_tests/managers/k8s/services.py b/tcp_tests/managers/k8s/services.py
new file mode 100644
index 0000000..97a6be7
--- /dev/null
+++ b/tcp_tests/managers/k8s/services.py
@@ -0,0 +1,68 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+
+
+from tcp_tests.managers.k8s.base import K8sBaseResource
+from tcp_tests.managers.k8s.base import K8sBaseManager
+
+
+class K8sService(K8sBaseResource):
+    """docstring for K8sService"""
+
+    def __repr__(self):
+        return "<K8sService: %s>" % self.name
+
+    @property
+    def name(self):
+        return self.metadata.name
+
+    @property
+    def namespace(self):
+        return self.metadata.namespace
+
+
+class K8sServiceManager(K8sBaseManager):
+    """docstring for K8sServiceManager"""
+
+    resource_class = K8sService
+
+    def _get(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.read_namespaced_service(
+            name=name, namespace=namespace, **kwargs)
+
+    def _list(self, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.list_namespaced_service(namespace=namespace, **kwargs)
+
+    def _create(self, body, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.create_namespaced_service(
+            body=body, namespace=namespace, **kwargs)
+
+    def _replace(self, body, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.replace_namespaced_service(
+            body=body, name=name, namespace=namespace, **kwargs)
+
+    def _delete(self, name, namespace=None, **kwargs):
+        namespace = namespace or self.namespace
+        return self.api.delete_namespaced_service(
+            name=name, namespace=namespace, **kwargs)
+
+    def full_list(self, *args, **kwargs):
+        lst = self._full_list(*args, **kwargs)
+        return [self.resource_class(self, item) for item in lst.items]
+
+    def _full_list(self, **kwargs):
+        return self.api.list_service(**kwargs)
diff --git a/tcp_tests/managers/k8smanager.py b/tcp_tests/managers/k8smanager.py
new file mode 100644
index 0000000..3801436
--- /dev/null
+++ b/tcp_tests/managers/k8smanager.py
@@ -0,0 +1,271 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import time
+
+import yaml
+
+from devops.helpers import helpers
+
+from tcp_tests import logger
+from tcp_tests.managers.execute_commands import ExecuteCommandsMixin
+from tcp_tests.managers.k8s import cluster
+
+
+LOG = logger.logger
+
+
+class K8SManager(ExecuteCommandsMixin):
+    """docstring for K8SManager"""
+
+    __config = None
+    __underlay = None
+
+    def __init__(self, config, underlay, salt):
+        self.__config = config
+        self.__underlay = underlay
+        self._salt = salt
+        self._api_client = None
+        super(K8SManager, self).__init__(
+            config=config, underlay=underlay)
+
+    def install(self, commands):
+        self.execute_commands(commands,
+                              label='Install Kubernetes services')
+        self.__config.k8s.k8s_installed = True
+        self.__config.k8s.kube_host = self.get_proxy_api()
+
+    def get_proxy_api(self):
+        k8s_proxy_ip_pillars = self._salt.get_pillar(
+            tgt='I@haproxy:proxy:enabled:true',
+            pillar='haproxy:proxy:listen:k8s_secure:binds:address')
+        k8s_proxy_ip = set([ip
+                            for item in k8s_proxy_ip_pillars
+                            for node,ip in item.items()])
+        assert len(k8s_proxy_ip) == 1, \
+            ("Found {0} Kubernetes endpoints in pillars,"
+             " expected one!").format(len(k8s_proxy_ip))
+        return k8s_proxy_ip.pop()
+
+    @property
+    def api(self):
+        if self._api_client is None:
+            self._api_client = cluster.K8sCluster(
+                user=self.__config.k8s_deploy.kubernetes_admin_user,
+                password=self.__config.k8s_deploy.kubernetes_admin_password,
+                host=self.__config.k8s.kube_host,
+                port=self.__config.k8s.kube_apiserver_port,
+                default_namespace='default')
+        return self._api_client
+
+    def get_pod_phase(self, pod_name, namespace=None):
+        return self.api.pods.get(
+            name=pod_name, namespace=namespace).phase
+
+    def wait_pod_phase(self, pod_name, phase, namespace=None, timeout=60):
+        """Wait phase of pod_name from namespace while timeout
+
+        :param str: pod_name
+        :param str: namespace
+        :param list or str: phase
+        :param int: timeout
+
+        :rtype: None
+        """
+        if isinstance(phase, str):
+            phase = [phase]
+
+        def check():
+            return self.get_pod_phase(pod_name, namespace) in phase
+
+        helpers.wait(check, timeout=timeout,
+                     timeout_msg='Timeout waiting, pod {pod_name} is not in '
+                                 '"{phase}" phase'.format(
+                                     pod_name=pod_name, phase=phase))
+
+    def wait_pods_phase(self, pods, phase, timeout=60):
+        """Wait timeout seconds for phase of pods
+
+        :param pods: list of K8sPod
+        :param phase: list or str
+        :param timeout: int
+
+        :rtype: None
+        """
+        if isinstance(phase, str):
+            phase = [phase]
+
+        def check(pod_name, namespace):
+            return self.get_pod_phase(pod_name, namespace) in phase
+
+        def check_all_pods():
+            return all(check(pod.name, pod.metadata.namespace) for pod in pods)
+
+        helpers.wait(
+            check_all_pods,
+            timeout=timeout,
+            timeout_msg='Timeout waiting, pods {0} are not in "{1}" '
+                        'phase'.format([pod.name for pod in pods], phase))
+
+    def check_pod_create(self, body, namespace=None, timeout=300, interval=5):
+        """Check creating sample pod
+
+        :param k8s_pod: V1Pod
+        :param namespace: str
+        :rtype: V1Pod
+        """
+        LOG.info("Creating pod in k8s cluster")
+        LOG.debug(
+            "POD spec to create:\n{}".format(
+                yaml.dump(body, default_flow_style=False))
+        )
+        LOG.debug("Timeout for creation is set to {}".format(timeout))
+        LOG.debug("Checking interval is set to {}".format(interval))
+        pod = self.api.pods.create(body=body, namespace=namespace)
+        pod.wait_running(timeout=300, interval=5)
+        LOG.info("Pod '{0}' is created in '{1}' namespace".format(
+            pod.name, pod.namespace))
+        return self.api.pods.get(name=pod.name, namespace=pod.namespace)
+
+    def wait_pod_deleted(self, podname, timeout=60, interval=5):
+        helpers.wait(
+            lambda: podname not in [pod.name for pod in self.api.pods.list()],
+            timeout=timeout,
+            interval=interval,
+            timeout_msg="Pod deletion timeout reached!"
+        )
+
+    def check_pod_delete(self, k8s_pod, timeout=300, interval=5,
+                         namespace=None):
+        """Deleting pod from k8s
+
+        :param k8s_pod: tcp_tests.managers.k8s.nodes.K8sNode
+        :param k8sclient: tcp_tests.managers.k8s.cluster.K8sCluster
+        """
+        LOG.info("Deleting pod '{}'".format(k8s_pod.name))
+        LOG.debug("Pod status:\n{}".format(k8s_pod.status))
+        LOG.debug("Timeout for deletion is set to {}".format(timeout))
+        LOG.debug("Checking interval is set to {}".format(interval))
+        self.api.pods.delete(body=k8s_pod, name=k8s_pod.name,
+                             namespace=namespace)
+        self.wait_pod_deleted(k8s_pod.name, timeout, interval)
+        LOG.debug("Pod '{}' is deleted".format(k8s_pod.name))
+
+    def check_service_create(self, body, namespace=None):
+        """Check creating k8s service
+
+        :param body: dict, service spec
+        :param namespace: str
+        :rtype: K8sService object
+        """
+        LOG.info("Creating service in k8s cluster")
+        LOG.debug(
+            "Service spec to create:\n{}".format(
+                yaml.dump(body, default_flow_style=False))
+        )
+        service = self.api.services.create(body=body, namespace=namespace)
+        LOG.info("Service '{0}' is created in '{1}' namespace".format(
+            service.name, service.namespace))
+        return self.api.services.get(name=service.name,
+                                     namespace=service.namespace)
+
+    def check_ds_create(self, body, namespace=None):
+        """Check creating k8s DaemonSet
+
+        :param body: dict, DaemonSet spec
+        :param namespace: str
+        :rtype: K8sDaemonSet object
+        """
+        LOG.info("Creating DaemonSet in k8s cluster")
+        LOG.debug(
+            "DaemonSet spec to create:\n{}".format(
+                yaml.dump(body, default_flow_style=False))
+        )
+        ds = self.api.daemonsets.create(body=body, namespace=namespace)
+        LOG.info("DaemonSet '{0}' is created  in '{1}' namespace".format(
+            ds.name, ds.namespace))
+        return self.api.daemonsets.get(name=ds.name, namespace=ds.namespace)
+
+    def check_ds_ready(self, dsname, namespace=None):
+        """Check if k8s DaemonSet is ready
+
+        :param dsname: str, ds name
+        :return: bool
+        """
+        ds = self.api.daemonsets.get(name=dsname, namespace=namespace)
+        return (ds.status.current_number_scheduled ==
+                ds.status.desired_number_scheduled)
+
+    def wait_ds_ready(self, dsname, namespace=None, timeout=60, interval=5):
+        """Wait until all pods are scheduled on nodes
+
+        :param dsname: str, ds name
+        :param timeout: int
+        :param interval: int
+        """
+        helpers.wait(
+            lambda: self.check_ds_ready(dsname, namespace=namespace),
+            timeout=timeout, interval=interval)
+
+    def check_namespace_create(self, name):
+        """Check creating k8s Namespace
+
+        :param name: str
+        :rtype: K8sNamespace object
+        """
+        LOG.info("Creating Namespace in k8s cluster")
+        ns = self.api.namespaces.create(body={'metadata': {'name': name}})
+        LOG.info("Namespace '{0}' is created".format(ns.name))
+        # wait 10 seconds until a token for new service account is created
+        time.sleep(10)
+        return self.api.namespaces.get(name=ns.name)
+
+    def create_objects(self, path):
+        if isinstance(path, str):
+            path = [path]
+        params = ' '.join(["-f {}".format(p) for p in path])
+        cmd = 'kubectl create {params}'.format(params=params)
+        with self.__underlay.remote(
+                host=self.__config.k8s.kube_host) as remote:
+            LOG.info("Running command '{cmd}' on node {node}".format(
+                cmd=cmd,
+                node=remote.hostname)
+            )
+            result = remote.check_call(cmd)
+            LOG.info(result['stdout'])
+
+    def get_running_pods(self, pod_name, namespace=None):
+        pods = [pod for pod in self.api.pods.list(namespace=namespace)
+                if (pod_name in pod.name and pod.status.phase == 'Running')]
+        return pods
+
+    def get_pods_number(self, pod_name, namespace=None):
+        pods = self.get_running_pods(pod_name, namespace)
+        return len(pods)
+
+    def get_running_pods_by_ssh(self, pod_name, namespace=None):
+        with self.__underlay.remote(
+                host=self.__config.k8s.kube_host) as remote:
+            result = remote.check_call("kubectl get pods --namespace {} |"
+                                       " grep {} | awk '{{print $1 \" \""
+                                       " $3}}'".format(namespace,
+                                                       pod_name))['stdout']
+            running_pods = [data.strip().split()[0] for data in result
+                            if data.strip().split()[1] == 'Running']
+            return running_pods
+
+    def get_pods_restarts(self, pod_name, namespace=None):
+        pods = [pod.status.container_statuses[0].restart_count
+                for pod in self.get_running_pods(pod_name, namespace)]
+        return sum(pods)
diff --git a/tcp_tests/managers/saltmanager.py b/tcp_tests/managers/saltmanager.py
index 304ff75..f8a3fd8 100644
--- a/tcp_tests/managers/saltmanager.py
+++ b/tcp_tests/managers/saltmanager.py
@@ -11,7 +11,6 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
-# import time
 
 from collections import defaultdict
 
@@ -151,3 +150,7 @@
             r = self.run_state(tgt=tgt, state=s, args=args, kwargs=kwargs)
             rets.append(r)
         return rets
+
+    def get_pillar(self, tgt, pillar):
+        result = self.local(tgt=tgt, fun='pillar.get', args=pillar)
+        return result['return']
diff --git a/tcp_tests/managers/virtlet_ceph_manager.py b/tcp_tests/managers/virtlet_ceph_manager.py
index 49c4c64..5a79cf2 100644
--- a/tcp_tests/managers/virtlet_ceph_manager.py
+++ b/tcp_tests/managers/virtlet_ceph_manager.py
@@ -21,10 +21,9 @@
     __config = None
     __underlay = None
 
-    def __init__(self, config, underlay, salt):
+    def __init__(self, config, underlay):
         self.__config = config
         self.__underlay = underlay
-        self._salt = salt
         super(VirtletCephManager, self).__init__(
             config=config, underlay=underlay)
 
diff --git a/tcp_tests/managers/virtlet_manager.py b/tcp_tests/managers/virtlet_manager.py
index c696ed4..f8d1ced 100644
--- a/tcp_tests/managers/virtlet_manager.py
+++ b/tcp_tests/managers/virtlet_manager.py
@@ -21,10 +21,9 @@
     __config = None
     __underlay = None
 
-    def __init__(self, config, underlay, salt):
+    def __init__(self, config, underlay):
         self.__config = config
         self.__underlay = underlay
-        self._salt = salt
         super(VirtletManager, self).__init__(
             config=config, underlay=underlay)