Merge "Added Ceph health test"
diff --git a/Dockerfile b/Dockerfile
index 8b77628..c6a1fe8 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,31 +6,32 @@
     DEBCONF_NONINTERACTIVE_SEEN=true \
     LANG=C.UTF-8 \
     LANGUAGE=$LANG
-SHELL ["/bin/bash", "-xeo", "pipefail", "-c"]
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
 
 USER root
 RUN mkdir -p /var/lib/cvp-sanity/
 COPY cvp-sanity/ /var/lib/cvp-sanity
+ARG UBUNTU_MIRROR_URL="http://archive.ubuntu.com/ubuntu"
 
 WORKDIR /var/lib/
 
-RUN pushd /etc/apt/ && echo > sources.list && \
-  echo 'Acquire::Languages "none";' > apt.conf.d/docker-no-languages && \
-  echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > apt.conf.d/docker-gzip-indexes && \
-  echo 'APT::Get::Install-Recommends "false"; APT::Get::Install-Suggests "false";' > apt.conf.d/docker-recommends && \
-  echo "deb [arch=amd64] http://cz.archive.ubuntu.com/ubuntu xenial main restricted universe multiverse" >> sources.list && \
-  echo "deb [arch=amd64] http://cz.archive.ubuntu.com/ubuntu xenial-updates main restricted universe multiverse" >> sources.list && \
-  echo "deb [arch=amd64] http://cz.archive.ubuntu.com/ubuntu xenial-backports main restricted universe multiverse" >> sources.list && \
-  popd ; apt-get update && apt-get  upgrade -y && \
-  apt-get install -y curl git-core iputils-ping libffi-dev libldap2-dev libsasl2-dev libssl-dev patch python-dev python-pip python3-dev vim-tiny wget \
-  python-virtualenv python3-virtualenv && \
+RUN set -ex; pushd /etc/apt/ && echo > sources.list && \
+    echo 'Acquire::Languages "none";' > apt.conf.d/docker-no-languages && \
+    echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > apt.conf.d/docker-gzip-indexes && \
+    echo 'APT::Get::Install-Recommends "false"; APT::Get::Install-Suggests "false";' > apt.conf.d/docker-recommends && \
+    echo "deb [arch=amd64] $UBUNTU_MIRROR_URL xenial main restricted universe multiverse" >> sources.list && \
+    echo "deb [arch=amd64] $UBUNTU_MIRROR_URL xenial-updates main restricted universe multiverse" >> sources.list && \
+    echo "deb [arch=amd64] $UBUNTU_MIRROR_URL xenial-backports main restricted universe multiverse" >> sources.list && \
+    popd ; apt-get update && apt-get  upgrade -y && \
+    apt-get install -y curl git-core iputils-ping libffi-dev libldap2-dev libsasl2-dev libssl-dev patch python-dev python-pip python3-dev vim-tiny wget \
+    python-virtualenv python3-virtualenv && \
 #Due to upstream bug we should use fixed version of pip
-  python -m pip install --upgrade 'pip==9.0.3' && \
-  pip install -r cvp-sanity/requirements.txt && \
+    python -m pip install --upgrade 'pip==9.0.3' && \
+    pip install -r cvp-sanity/requirements.txt && \
 # Cleanup
-  apt-get -y purge libx11-data xauth libxmuu1 libxcb1 libx11-6 libxext6 ppp pppconfig pppoeconf popularity-contest cpp gcc g++ libssl-doc && \
-  apt-get -y autoremove; apt-get -y clean ; rm -rf /root/.cache; rm -rf /var/lib/apt/lists/* && \
-  rm -rf /tmp/* ; rm -rf /var/tmp/* ; rm -rfv /etc/apt/sources.list.d/* ; echo > /etc/apt/sources.list
+    apt-get -y purge libx11-data xauth libxmuu1 libxcb1 libx11-6 libxext6 ppp pppconfig pppoeconf popularity-contest cpp gcc g++ libssl-doc && \
+    apt-get -y autoremove; apt-get -y clean ; rm -rf /root/.cache; rm -rf /var/lib/apt/lists/* && \
+    rm -rf /tmp/* ; rm -rf /var/tmp/* ; rm -rfv /etc/apt/sources.list.d/* ; echo > /etc/apt/sources.list
 COPY bin /usr/local/bin/
 ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
 # docker build --no-cache -t cvp-sanity-checks:$(date "+%Y_%m_%d_%H_%M_%S") .
diff --git a/cvp-sanity/cvp_checks/tests/test_drivetrain.py b/cvp-sanity/cvp_checks/tests/test_drivetrain.py
index 3f333c7..20c90d1 100644
--- a/cvp-sanity/cvp_checks/tests/test_drivetrain.py
+++ b/cvp-sanity/cvp_checks/tests/test_drivetrain.py
@@ -266,9 +266,10 @@
         'cmd.run',
         ['docker service ls'],
         expr_form='compound')
+    #  'ldap_server' removed because it is an external component now v 1.1.8
     not_found_services = ['gerrit_db', 'gerrit_server', 'jenkins_master',
                           'jenkins_slave01', 'jenkins_slave02',
-                          'jenkins_slave03', 'ldap_admin', 'ldap_server']
+                          'jenkins_slave03', 'ldap_admin']
     version_mismatch = []
     for line in salt_output[salt_output.keys()[0]].split('\n'):
         for service in not_found_services:
diff --git a/cvp-sanity/cvp_checks/tests/test_services.py b/cvp-sanity/cvp_checks/tests/test_services.py
index a623508..95dfb51 100644
--- a/cvp-sanity/cvp_checks/tests/test_services.py
+++ b/cvp-sanity/cvp_checks/tests/test_services.py
@@ -3,8 +3,18 @@
 import os
 from cvp_checks import utils
 
+# Some nodes can have services that are not applicable for other noder in similar group.
+# For example , there are 3 node in kvm group, but just kvm03 node has srv-volumes-backup.mount service
+# in service.get_all
+#                        NODE NAME          SERVICE_NAME
+inconsistency_rule = {"kvm03": ["srv-volumes-backup.mount", "rsync"]}
+
 
 def test_check_services(local_salt_client, nodes_in_group):
+    """
+    Skips services if they are not consistent for all node.
+    Inconsistent services will be checked with another test case
+    """
     output = local_salt_client.cmd("L@"+','.join(nodes_in_group), 'service.get_all', expr_form='compound')
 
     if len(output.keys()) < 2:
@@ -22,15 +32,83 @@
         diff = []
         row = []
         for node in nodes:
-            if srv in output[node]:
+            short_name_of_node = node.split('.')[0]
+            if inconsistency_rule.get(short_name_of_node) is not None and srv in inconsistency_rule[short_name_of_node]:
+                # Found service on node and it SHOULD be there
+                break
+            elif srv in output[node]:
+                # Found service on node
                 diff.append(srv)
                 row.append("{}: +".format(node))
             else:
+                # Not found expected service on node
                 row.append("{}: No service".format(node))
-        if diff.count(diff[0]) < len(nodes):
+        if diff.__len__() > 0 and diff.count(diff[0]) < len(nodes):
             row.sort()
             row.insert(0, srv)
             pkts_data.append(row)
-    assert len(pkts_data) <= 1, \
+    assert len(pkts_data) == 0, \
         "Several problems found: {0}".format(
         json.dumps(pkts_data, indent=4))
+
+
+# TODO : remake this test to make workable https://mirantis.jira.com/browse/PROD-25958
+
+# def _check_services_on_special_node(local_salt_client, nodes_in_group):
+#     """
+#     Check that specific node has service.
+#     Nodes and proper services should be defined in inconsistency_rule dictionary
+#
+#     :print: Table with nodes which don't have required services and not existed services
+#     """
+#
+#     output = local_salt_client.cmd("L@" + ','.join(nodes_in_group), 'service.get_all', expr_form='compound')
+#     if len(output.keys()) < 2:
+#         pytest.skip("Nothing to compare - just 1 node")
+#
+#     def is_proper_service_for_node(_service, _node):
+#         """
+#         Return True if service exists on node and exists in inconsistency_rule
+#         Return True if service doesn't exists on node and doesn't exists in inconsistency_rule
+#         Return False otherwise
+#         :param _service: string
+#         :param _node: string full name of node
+#         :return: bool, read description for further details
+#         """
+#         short_name_of_node = _node.split('.')[0]
+#         if short_name_of_node not in inconsistency_rule.keys():
+#             return False
+#
+#         if _service in inconsistency_rule[short_name_of_node] and \
+#                 _service in output[_node]:
+#             # Return True if service exists on node and exists in inconsistency_rule
+#             return True
+#
+#         if _service not in inconsistency_rule[short_name_of_node] and \
+#                 _service not in output[_node]:
+#             # Return True if service exists on node and exists in inconsistency_rule
+#             return True
+#         print("return False for {} in {}".format(_service, _node))
+#         # error_text = ""
+#         return False
+#
+#     errors = list()
+#     for node, expected_services in inconsistency_rule.items():
+#         print("Check {} , {} ".format(node, expected_services))
+#         # Skip if there is no proper node. Find nodes that contains node_title (like 'kvm03') in their titles
+#         if not any([node in node_name for node_name in output.keys()]):
+#             continue
+#         for expected_service in expected_services:
+#             service_on_nodes = {_node: expected_service if expected_service in _service else None
+#                                 for _node, _service
+#                                 in output.items()}
+#             print([is_proper_service_for_node(expected_service, _node)
+#                   for _node
+#                   in output.keys()])
+#             if not all([is_proper_service_for_node(expected_service, _node)
+#                         for _node
+#                         in output.keys()]):
+#                 errors.append(service_on_nodes)
+#
+#     assert errors.__len__() == 0, json.dumps(errors, indent=4)
+#     assert False