Merge "Add new cookied model for baremetal"
diff --git "a/tcp_tests/environment/environment_template/\173\043 roles \043\175/openstack_database" "b/tcp_tests/environment/environment_template/\173\043 roles \043\175/openstack_database"
index 5bc6aee..3c3c87f 100644
--- "a/tcp_tests/environment/environment_template/\173\043 roles \043\175/openstack_database"
+++ "b/tcp_tests/environment/environment_template/\173\043 roles \043\175/openstack_database"
@@ -7,6 +7,7 @@
           classes:
 #}
           - cluster.${_param:cluster_name}.openstack.database
+          - service.galera.slave.cluster
 {{- set_param('keepalived_vip_interface', 'br_ctl') }}
 {{- register_metaparam('mysql_cluster_role', 'openstack_database') }}
 {{- register_metaparam('keepalived_vip_priority', 'openstack_database') }}
diff --git "a/tcp_tests/environment/environment_template/\173\043 roles \043\175/openstack_database_leader" "b/tcp_tests/environment/environment_template/\173\043 roles \043\175/openstack_database_leader"
index 1f855fe..c8e2112 100644
--- "a/tcp_tests/environment/environment_template/\173\043 roles \043\175/openstack_database_leader"
+++ "b/tcp_tests/environment/environment_template/\173\043 roles \043\175/openstack_database_leader"
@@ -7,4 +7,5 @@
           classes:
 #}
           {%- include ("{# roles #}/" + 'openstack_database') %}
-          - cluster.${_param:cluster_name}.openstack.database_init
\ No newline at end of file
+          - cluster.${_param:cluster_name}.openstack.database_init
+          - service.galera.master.cluster
\ No newline at end of file
diff --git a/tcp_tests/fixtures/underlay_fixtures.py b/tcp_tests/fixtures/underlay_fixtures.py
index e1420b5..a1476e3 100644
--- a/tcp_tests/fixtures/underlay_fixtures.py
+++ b/tcp_tests/fixtures/underlay_fixtures.py
@@ -196,3 +196,26 @@
         underlay = underlay_ssh_manager.UnderlaySSHManager(config)
 
     return underlay
+
+
+@pytest.fixture(scope='function', autouse=True)
+def grab_versions(request, underlay):
+    """Fixture for grab package versions at the end of test
+
+    Marks:
+        grab_versions(name=None) - make snapshot if test is passed. If
+        name argument provided, it will be used for creating data,
+        otherwise, test function name will be used
+
+    """
+    grab_version = request.keywords.get('grab_versions', None)
+
+    def test_fin():
+        default_name = getattr(request.node.function, '_name',
+                               request.node.function.__name__)
+        if hasattr(request.node, 'rep_call') and request.node.rep_call.passed \
+                and grab_version:
+            artifact_name = utils.extract_name_from_mark(grab_version) or \
+                "{}".format(default_name)
+            underlay.get_logs(artifact_name)
+    request.addfinalizer(test_fin)
diff --git a/tcp_tests/helpers/ext.py b/tcp_tests/helpers/ext.py
index f7b8005..99baaff 100644
--- a/tcp_tests/helpers/ext.py
+++ b/tcp_tests/helpers/ext.py
@@ -26,6 +26,7 @@
     'salt_master',
     'salt_minion',
     'k8s_virtlet',
+    'k8s_controller',
     'decapod_mon',
     'decapod_osd',
     'decapod_all',
diff --git a/tcp_tests/managers/k8smanager.py b/tcp_tests/managers/k8smanager.py
index d84fd73..87e3eaf 100644
--- a/tcp_tests/managers/k8smanager.py
+++ b/tcp_tests/managers/k8smanager.py
@@ -17,8 +17,11 @@
 import yaml
 
 from devops.helpers import helpers
+from devops.error import DevopsCalledProcessError
 
 from tcp_tests import logger
+from tcp_tests.helpers import ext
+from tcp_tests.helpers.utils import retry
 from tcp_tests.managers.execute_commands import ExecuteCommandsMixin
 from tcp_tests.managers.k8s import cluster
 from k8sclient.client.rest import ApiException
@@ -80,6 +83,12 @@
                 default_namespace='default')
         return self._api_client
 
+    @property
+    def ctl_host(self):
+        nodes = [node for node in self.__config.underlay.ssh if
+                 ext.UNDERLAY_NODE_ROLES.k8s_controller in node['roles']]
+        return nodes[0]['node_name']
+
     def get_pod_phase(self, pod_name, namespace=None):
         return self.api.pods.get(
             name=pod_name, namespace=namespace).phase
@@ -296,7 +305,7 @@
         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:
+                node_name=self.ctl_host) as remote:
             LOG.info("Running command '{cmd}' on node {node}".format(
                 cmd=cmd,
                 node=remote.hostname)
@@ -315,7 +324,7 @@
 
     def get_running_pods_by_ssh(self, pod_name, namespace=None):
         with self.__underlay.remote(
-                host=self.__config.k8s.kube_host) as remote:
+                node_name=self.ctl_host) as remote:
             result = remote.check_call("kubectl get pods --namespace {} |"
                                        " grep {} | awk '{{print $1 \" \""
                                        " $3}}'".format(namespace,
@@ -331,7 +340,7 @@
 
     def run_conformance(self, timeout=60 * 60):
         with self.__underlay.remote(
-                host=self.__config.k8s.kube_host) as remote:
+                node_name=self.ctl_host) as remote:
             result = remote.check_call(
                 "docker run --rm --net=host -e API_SERVER="
                 "'http://127.0.0.1:8080' {}".format(
@@ -347,7 +356,7 @@
 
     def kubectl_run(self, name, image, port):
         with self.__underlay.remote(
-                host=self.__config.k8s.kube_host) as remote:
+                node_name=self.ctl_host) as remote:
             result = remote.check_call(
                 "kubectl run {0} --image={1} --port={2}".format(
                     name, image, port
@@ -357,7 +366,7 @@
 
     def kubectl_expose(self, resource, name, port, type):
         with self.__underlay.remote(
-                host=self.__config.k8s.kube_host) as remote:
+                node_name=self.ctl_host) as remote:
             result = remote.check_call(
                 "kubectl expose {0} {1} --port={2} --type={3}".format(
                     resource, name, port, type
@@ -365,27 +374,28 @@
             )
             return result
 
-    def kubectl_annotate(self, resource, name, annotaion):
+    def kubectl_annotate(self, resource, name, annotation):
         with self.__underlay.remote(
-                host=self.__config.k8s.kube_host) as remote:
+                node_name=self.ctl_host) as remote:
             result = remote.check_call(
-                "kubectl annotate {0} {1} {3}".format(
-                    resource, name, annotaion
+                "kubectl annotate {0} {1} {2}".format(
+                    resource, name, annotation
                 )
             )
             return result
 
-    def get_svc_ip(self, name):
+    def get_svc_ip(self, name, namespace='kube-system'):
         with self.__underlay.remote(
-                host=self.__config.k8s.kube_host) as remote:
+                node_name=self.ctl_host) as remote:
             result = remote.check_call(
-                "kubectl get svc --all-namespaces | grep {0} | "
-                "awk '{{print $2}}'".format(name)
+                "kubectl get svc {0} -n {1} | "
+                "awk '{{print $2}}' | tail -1".format(name, namespace)
             )
             return result['stdout'][0].strip()
 
+    @retry(300, exception=DevopsCalledProcessError)
     def nslookup(self, host, src):
         with self.__underlay.remote(
-                host=self.__config.k8s.kube_host) as remote:
+                node_name=self.ctl_host) as remote:
             remote.check_call("nslookup {0} {1}".format(host, src))
 
diff --git a/tcp_tests/managers/underlay_ssh_manager.py b/tcp_tests/managers/underlay_ssh_manager.py
index 53f5aee..12ea22d 100644
--- a/tcp_tests/managers/underlay_ssh_manager.py
+++ b/tcp_tests/managers/underlay_ssh_manager.py
@@ -12,6 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import os
 import random
 import StringIO
 
@@ -22,6 +23,7 @@
 import yaml
 
 from tcp_tests import logger
+from tcp_tests.helpers import ext
 from tcp_tests.helpers import utils
 
 LOG = logger.logger
@@ -390,3 +392,40 @@
         }
         template = utils.render_template(file_path, options=options)
         return yaml.load(template)
+
+    def get_logs(self, artifact_name,
+                 node_role=ext.UNDERLAY_NODE_ROLES.salt_master):
+        master_node = [ssh for ssh in self.config_ssh
+                       if node_role in ssh['roles']][0]
+        cmd = ("dpkg -l | grep formula > "
+               "/var/log/{0}_packages.output".format(master_node['node_name']))
+
+        tar_cmd = ('tar --absolute-names'
+                   ' --warning=no-file-changed '
+                   '-czf {t} {d}'.format(
+            t='{0}_log.tar.gz'.format(artifact_name), d='/var/log'))
+        minion_nodes = [ssh for ssh in self.config_ssh
+                        if node_role not in ssh['roles']]
+        for node in minion_nodes:
+            with self.remote(host=node['host']) as r_node:
+                r_node.check_call(('tar '
+                                   '--absolute-names '
+                                   '--warning=no-file-changed '
+                                   '-czf {t} {d}'.format(
+                    t='{0}.tar.gz'.format(node['node_name']), d='/var/log')),
+                    verbose=True, raise_on_err=False)
+        with self.remote(master_node['node_name']) as r:
+            for node in minion_nodes:
+                packages_minion_cmd = ("salt '{0}*' cmd.run "
+                                       "'dpkg -l' > /var/log/"
+                                       "{0}_packages.output".format(
+                    node['node_name']))
+                r.check_call(packages_minion_cmd)
+                r.check_call("rsync {0}:/root/*.tar.gz "
+                             "/var/log/".format(node['node_name']),
+                             verbose=True, raise_on_err=False)
+            r.check_call(cmd)
+
+            r.check_call(tar_cmd)
+            r.download(destination='{0}_log.tar.gz'.format(artifact_name),
+                       target=os.getcwd())
diff --git a/tcp_tests/settings_oslo.py b/tcp_tests/settings_oslo.py
index cc50762..7a2d82d 100644
--- a/tcp_tests/settings_oslo.py
+++ b/tcp_tests/settings_oslo.py
@@ -94,7 +94,8 @@
            help="Node roles managed by underlay in the environment",
            default=[ext.UNDERLAY_NODE_ROLES.salt_master,
                     ext.UNDERLAY_NODE_ROLES.salt_minion,
-                    ext.UNDERLAY_NODE_ROLES.k8s_virtlet, ]),
+                    ext.UNDERLAY_NODE_ROLES.k8s_virtlet,
+                    ext.UNDERLAY_NODE_ROLES.k8s_controller]),
     ct.Cfg('bootstrap_timeout', ct.Integer(),
            help="Timeout of waiting SSH for nodes with specified roles",
            default=480),
@@ -278,7 +279,7 @@
     ct.Cfg('kubernetes_virtlet_enabled', ct.Boolean(),
            help="", default=False),
     ct.Cfg('kubernetes_virtlet_image', ct.String(),
-           help="", default='mirantis/virtlet:v0.7.0'),
+           help="", default='mirantis/virtlet:v0.8.0'),
     ct.Cfg('kubernetes_externaldns_enabled', ct.Boolean(),
            help="", default=False),
     ct.Cfg('kubernetes_externaldns_image', ct.String(),
diff --git a/tcp_tests/templates/cookied-mcp-ocata-dop-sl2/common-services.yaml b/tcp_tests/templates/cookied-mcp-ocata-dop-sl2/common-services.yaml
index ea2997a..cf66773 100644
--- a/tcp_tests/templates/cookied-mcp-ocata-dop-sl2/common-services.yaml
+++ b/tcp_tests/templates/cookied-mcp-ocata-dop-sl2/common-services.yaml
@@ -1,5 +1,11 @@
 {% from 'cookied-mcp-ocata-dop-sl2/underlay.yaml' import HOSTNAME_CFG01 with context %}
 
+- description: Refresh grains
+  cmd: salt --hard-crash --state-output=mixed --state-verbose=False '*' state.sls salt.minion.grains
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 15}
+  skip_fail: false
+
 # Install support services
 - description: Install keepalived on ctl01
   cmd: salt --hard-crash --state-output=mixed --state-verbose=False
diff --git a/tcp_tests/templates/cookied-mcp-ocata-dvr-vxlan/common-services.yaml b/tcp_tests/templates/cookied-mcp-ocata-dvr-vxlan/common-services.yaml
index 1deca4b..b2d0751 100644
--- a/tcp_tests/templates/cookied-mcp-ocata-dvr-vxlan/common-services.yaml
+++ b/tcp_tests/templates/cookied-mcp-ocata-dvr-vxlan/common-services.yaml
@@ -1,5 +1,11 @@
 {% from 'cookied-mcp-ocata-dvr-vxlan/underlay.yaml' import HOSTNAME_CFG01 with context %}
 
+- description: Refresh grains
+  cmd: salt --hard-crash --state-output=mixed --state-verbose=False '*' state.sls salt.minion.grains
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 15}
+  skip_fail: false
+
 # Install support services
 - description: Install keepalived on ctl01
   cmd: salt --hard-crash --state-output=mixed --state-verbose=False
diff --git a/tcp_tests/templates/local_dns/underlay--meta-data.yaml b/tcp_tests/templates/local_dns/underlay--meta-data.yaml
new file mode 100644
index 0000000..3699401
--- /dev/null
+++ b/tcp_tests/templates/local_dns/underlay--meta-data.yaml
@@ -0,0 +1,4 @@
+| # All the data below will be stored as a string object
+  instance-id: iid-local1
+  hostname: {hostname}
+  local-hostname: {hostname}
diff --git a/tcp_tests/templates/local_dns/underlay--user-data1604.yaml b/tcp_tests/templates/local_dns/underlay--user-data1604.yaml
new file mode 100644
index 0000000..f60c4c2
--- /dev/null
+++ b/tcp_tests/templates/local_dns/underlay--user-data1604.yaml
@@ -0,0 +1,102 @@
+| # All the data below will be stored as a string object
+  #cloud-config, see http://cloudinit.readthedocs.io/en/latest/topics/examples.html
+
+  ssh_pwauth: True
+  users:
+   - name: root
+     sudo: ALL=(ALL) NOPASSWD:ALL
+     shell: /bin/bash
+     ssh_authorized_keys:
+     {% for key in config.underlay.ssh_keys %}
+      - ssh-rsa {{ key['public'] }}
+     {% endfor %}
+
+  disable_root: false
+  chpasswd:
+   list: |
+    root:r00tme
+   expire: False
+
+  bootcmd:
+   # Block access to SSH while node is preparing
+   - cloud-init-per once sudo iptables -A INPUT -p tcp --dport 22 -j DROP
+   # Enable root access
+   - sed -i -e '/^PermitRootLogin/s/^.*$/PermitRootLogin yes/' /etc/ssh/sshd_config
+   - service sshd restart
+  output:
+    all: '| tee -a /var/log/cloud-init-output.log /dev/tty0'
+
+  runcmd:
+   - export TERM=linux
+   - export LANG=C
+   # Configure dhclient
+   - sudo echo "nameserver {gateway}" >> /etc/resolvconf/resolv.conf.d/base
+   - sudo resolvconf -u
+
+   # Prepare network connection
+   - sudo ifup ens3
+   #- sudo route add default gw {gateway} {interface_name}
+   - sudo ifup ens4
+
+   # Create swap
+   - fallocate -l 4G /swapfile
+   - chmod 600 /swapfile
+   - mkswap /swapfile
+   - swapon /swapfile
+   - echo "/swapfile   none    swap    defaults   0   0" >> /etc/fstab
+
+
+   ############## Cloud repo01 node ##################
+   - echo "nameserver 172.18.208.44" >> /etc/resolv.conf;
+   - echo "nameserver 8.8.8.8" >> /etc/resolv.conf;
+   - export LOCAL_DNS_IP=$(ifconfig ens3 | grep "inet addr" | cut -d ':' -f 2 | cut -d ' ' -f 1)
+   - which wget >/dev/null || (apt-get update; apt-get install -y wget);
+
+   - echo "deb [arch=amd64] http://apt.mirantis.com/xenial {{ REPOSITORY_SUITE }} salt extra" > /etc/apt/sources.list.d/mcp_salt.list;
+   - wget -O - http://apt.mirantis.com/public.gpg | apt-key add -;
+   - echo "deb http://repo.saltstack.com/apt/ubuntu/16.04/amd64/2016.3 xenial main" > /etc/apt/sources.list.d/saltstack.list;
+   - wget -O - https://repo.saltstack.com/apt/ubuntu/16.04/amd64/2016.3/SALTSTACK-GPG-KEY.pub | apt-key add -;
+
+   - eatmydata apt-get clean && apt-get update
+
+   # Install common packages
+   - eatmydata apt-get install -y salt-minion python-pip git curl tmux byobu iputils-ping traceroute htop tree;
+   - cd /tmp;
+   - git clone https://github.com/TatyankaLeontovich/salt-formula-nginx;
+   - git clone https://github.com/TatyankaLeontovich/salt-dnsmasq;
+   - git clone https://github.com/TatyankaLeontovich/underpillar;
+   - mkdir -p /srv/pillar/;
+   - mkdir -p /srv/salt;
+   - cd /srv/salt;
+   - ln -s /tmp/salt-formula-nginx/nginx;
+   - ln -s /tmp/salt-dnsmasq/dnsmasq;
+   - cp /tmp/underpillar/pillar/*.sls /srv/pillar/;
+   - cp /tmp/underpillar/states/*.sls /srv/salt/;
+   - cp /srv/pillar/top_localdns.sls /srv/pillar/top.sls;
+   - cp /srv/salt/top_localdns.sls /srv/salt/top.sls;
+   - find /srv/pillar/ -type f -exec sed -i "s/==LOCAL_DNS_IP==/${LOCAL_DNS_IP}/g" {} +
+   - salt-call --local  --state-output=mixed state.sls dnsmasq;
+   - salt-call --local  --state-output=mixed state.sls nginx;
+   ########################################################
+   # Node is ready, allow SSH access
+   - echo "Allow SSH access ..."
+   - sudo iptables -D INPUT -p tcp --dport 22 -j DROP
+   ########################################################
+
+  write_files:
+   - path: /etc/network/interfaces
+     content: |
+          auto ens3
+          iface ens3 inet dhcp
+          auto ens4
+          iface ens4 inet dhcp
+
+   - path: /root/.ssh/config
+     owner: root:root
+     permissions: '0600'
+     content: |
+          Host *
+            ServerAliveInterval 300
+            ServerAliveCountMax 10
+            StrictHostKeyChecking no
+            UserKnownHostsFile /dev/null
\ No newline at end of file
diff --git a/tcp_tests/templates/local_dns/underlay.yaml b/tcp_tests/templates/local_dns/underlay.yaml
new file mode 100644
index 0000000..041f934
--- /dev/null
+++ b/tcp_tests/templates/local_dns/underlay.yaml
@@ -0,0 +1,112 @@
+# Set the repository suite, one of the: 'nightly', 'testing', 'stable', or any other required
+{% set REPOSITORY_SUITE = os_env('REPOSITORY_SUITE', 'testing') %}
+
+{% import 'local_dns/underlay--meta-data.yaml' as CLOUDINIT_META_DATA with context %}
+{% import 'local_dns/underlay--user-data1604.yaml' as CLOUDINIT_USER_DATA_1604 with context %}
+
+---
+aliases:
+ - &interface_model {{ os_env('INTERFACE_MODEL', 'virtio') }}
+ - &cloudinit_meta_data {{ CLOUDINIT_META_DATA }}
+ - &cloudinit_user_data_1604 {{ CLOUDINIT_USER_DATA_1604 }}
+
+{% set DOMAIN_NAME = os_env('LAB_CONFIG_NAME', 'local_dns') + '.local' %}
+{% set HOSTNAME_REPO01 = os_env('HOSTNAME_REPO01', 'repo01.' + DOMAIN_NAME) %}
+
+template:
+  devops_settings:
+    env_name: {{ os_env('ENV_NAME', 'local_dns_' + REPOSITORY_SUITE + "_" + os_env('BUILD_NUMBER', '')) }}
+
+    address_pools:
+      private-pool01:
+        net: {{ os_env('PRIVATE_ADDRESS_POOL01', '10.60.0.0/16:24') }}
+        params:
+          ip_reserved:
+            gateway: +1
+            l2_network_device: +1
+            default_{{ HOSTNAME_REPO01 }}: +122
+          ip_ranges:
+            dhcp: [+90, -10]
+
+      admin-pool01:
+        net: {{ os_env('ADMIN_ADDRESS_POOL01', '10.70.0.0/16:24') }}
+        params:
+          ip_reserved:
+            gateway: +1
+            l2_network_device: +1
+            default_{{ HOSTNAME_REPO01 }}: +122
+          ip_ranges:
+            dhcp: [+90, -10]
+
+    groups:
+      - name: default
+        driver:
+          name: devops.driver.libvirt
+          params:
+            connection_string: !os_env CONNECTION_STRING, qemu:///system
+            storage_pool_name: !os_env STORAGE_POOL_NAME, default
+            stp: False
+            hpet: False
+            enable_acpi: true
+            use_host_cpu: !os_env DRIVER_USE_HOST_CPU, true
+            use_hugepages: !os_env DRIVER_USE_HUGEPAGES, false
+
+        network_pools:
+          admin: admin-pool01
+          private: private-pool01
+
+        l2_network_devices:
+          private:
+            address_pool: private-pool01
+            dhcp: true
+
+          admin:
+            address_pool: admin-pool01
+            dhcp: true
+            forward:
+              mode: nat
+
+        group_volumes:
+         - name: cloudimage1604    # This name is used for 'backing_store' option for node volumes.
+           source_image: !os_env IMAGE_PATH1604  # https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img or
+                                             # http://apt.tcpcloud.eu/images/ubuntu-16-04-x64-201608231004.qcow2
+           format: qcow2
+
+        nodes:
+          - name: {{ HOSTNAME_REPO01 }}
+            role: local_repo
+            params:
+              vcpu: !os_env SLAVE_NODE_CPU, 2
+              memory: !os_env SLAVE_NODE_MEMORY, 2048
+              boot:
+                - hd
+              cloud_init_volume_name: iso
+              cloud_init_iface_up: ens3
+              volumes:
+                - name: system
+                  capacity: !os_env NODE_VOLUME_SIZE, 150
+                  backing_store: cloudimage1604
+                  format: qcow2
+                - name: iso  # Volume with name 'iso' will be used
+                             # for store image with cloud-init metadata.
+                  capacity: 1
+                  format: raw
+                  device: cdrom
+                  bus: ide
+                  cloudinit_meta_data: *cloudinit_meta_data
+                  cloudinit_user_data: *cloudinit_user_data_1604
+
+              interfaces:
+                - label: ens3
+                  l2_network_device: admin
+                  interface_model: *interface_model
+                - label: ens4
+                  l2_network_device: private
+                  interface_model: *interface_model
+              network_config:
+                ens3:
+                  networks:
+                    - admin
+                ens4:
+                  networks:
+                    - private
diff --git a/tcp_tests/templates/physical_mcp11_ovs_dpdk/common-services.yaml b/tcp_tests/templates/physical_mcp11_ovs_dpdk/common-services.yaml
index 1728329..bbbd2f5 100644
--- a/tcp_tests/templates/physical_mcp11_ovs_dpdk/common-services.yaml
+++ b/tcp_tests/templates/physical_mcp11_ovs_dpdk/common-services.yaml
@@ -1,5 +1,11 @@
 {% from 'physical_mcp11_ovs_dpdk/underlay.yaml' import HOSTNAME_CFG01 with context %}
 
+- description: Refresh grains
+  cmd: salt --hard-crash --state-output=mixed --state-verbose=False '*' state.sls salt.minion.grains
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 15}
+  skip_fail: false
+
 # Install support services
 - description: Install keepalived on ctl01
   cmd: salt --hard-crash --state-output=mixed --state-verbose=False
diff --git a/tcp_tests/templates/virtual-mcp-ocata-dvr/openstack.yaml b/tcp_tests/templates/virtual-mcp-ocata-dvr/openstack.yaml
index 966b7c1..dad874b 100644
--- a/tcp_tests/templates/virtual-mcp-ocata-dvr/openstack.yaml
+++ b/tcp_tests/templates/virtual-mcp-ocata-dvr/openstack.yaml
@@ -136,7 +136,7 @@
 # isntall designate
 - description: Install powerdns
   cmd: salt --hard-crash --state-output=mixed --state-verbose=False
-    -C 'ctl*' state.sls powerdns
+    -C 'I@powerdns:server' state.sls powerdns.server
   node_name: {{ HOSTNAME_CFG01 }}
   retry: {count: 1, delay: 5}
   skip_fail: false
diff --git a/tcp_tests/templates/virtual-mcp11-dvr/salt.yaml b/tcp_tests/templates/virtual-mcp11-dvr/salt.yaml
index 7c054ff..ece01ce 100644
--- a/tcp_tests/templates/virtual-mcp11-dvr/salt.yaml
+++ b/tcp_tests/templates/virtual-mcp11-dvr/salt.yaml
@@ -22,19 +22,19 @@
 {{ SHARED.MACRO_BOOTSTRAP_ALL_MINIONS() }}
 
 - description: Hack gtw node
-  cmd: salt 'gtw*' cmd.run "ip addr del {{ SHARED.IPV4_NET_CONTROL_PREFIX }}.110/24 dev ens4; ip addr flush dev ens4";
+  cmd: salt 'gtw*' cmd.run "ip addr del {{ SHARED.IPV4_NET_CONTROL_PREFIX }}.94/24 dev ens4; ip addr flush dev ens4";
   node_name: {{ HOSTNAME_CFG01 }}
   retry: {count: 1, delay: 10}
   skip_fail: false
 
 - description: Hack cmp01 node
-  cmd: salt 'cmp01*' cmd.run "ip addr del {{ SHARED.IPV4_NET_CONTROL_PREFIX }}.105/24 dev ens4; ip addr flush dev ens4";
+  cmd: salt 'cmp01*' cmd.run "ip addr del {{ SHARED.IPV4_NET_CONTROL_PREFIX }}.95/24 dev ens4; ip addr flush dev ens4";
   node_name: {{ HOSTNAME_CFG01 }}
   retry: {count: 1, delay: 10}
   skip_fail: false
 
 - description: Hack cmp02 node
-  cmd: salt 'cmp02*' cmd.run "ip addr del {{ SHARED.IPV4_NET_CONTROL_PREFIX }}.106/24 dev ens4; ip addr flush dev ens4";
+  cmd: salt 'cmp02*' cmd.run "ip addr del {{ SHARED.IPV4_NET_CONTROL_PREFIX }}.96/24 dev ens4; ip addr flush dev ens4";
   node_name: {{ HOSTNAME_CFG01 }}
   retry: {count: 1, delay: 10}
   skip_fail: false
diff --git a/tcp_tests/templates/virtual-mcp11-dvr/underlay.yaml b/tcp_tests/templates/virtual-mcp11-dvr/underlay.yaml
index 94f31fd..8ba5656 100644
--- a/tcp_tests/templates/virtual-mcp11-dvr/underlay.yaml
+++ b/tcp_tests/templates/virtual-mcp11-dvr/underlay.yaml
@@ -34,13 +34,13 @@
           ip_reserved:
             gateway: +1
             l2_network_device: +1
-            default_{{ HOSTNAME_CFG01 }}: +100
-            default_{{ HOSTNAME_CTL01 }}: +101
-            default_{{ HOSTNAME_CTL02 }}: +102
-            default_{{ HOSTNAME_CTL03 }}: +103
-            default_{{ HOSTNAME_CMP01 }}: +105
-            default_{{ HOSTNAME_CMP02 }}: +106
-            default_{{ HOSTNAME_GTW01 }}: +110
+            default_{{ HOSTNAME_CFG01 }}: +90
+            default_{{ HOSTNAME_CTL01 }}: +91
+            default_{{ HOSTNAME_CTL02 }}: +92
+            default_{{ HOSTNAME_CTL03 }}: +93
+            default_{{ HOSTNAME_CMP01 }}: +95
+            default_{{ HOSTNAME_CMP02 }}: +96
+            default_{{ HOSTNAME_GTW01 }}: +94
             default_{{ HOSTNAME_PRX01 }}: +121
           ip_ranges:
             dhcp: [+90, -10]
@@ -52,12 +52,12 @@
             gateway: +1
             l2_network_device: +1
             default_{{ HOSTNAME_CFG01 }}: +90
-            default_{{ HOSTNAME_CTL01 }}: +101
-            default_{{ HOSTNAME_CTL02 }}: +102
-            default_{{ HOSTNAME_CTL03 }}: +103
-            default_{{ HOSTNAME_CMP01 }}: +105
-            default_{{ HOSTNAME_CMP02 }}: +106
-            default_{{ HOSTNAME_GTW01 }}: +110
+            default_{{ HOSTNAME_CTL01 }}: +91
+            default_{{ HOSTNAME_CTL02 }}: +92
+            default_{{ HOSTNAME_CTL03 }}: +93
+            default_{{ HOSTNAME_CMP01 }}: +95
+            default_{{ HOSTNAME_CMP02 }}: +96
+            default_{{ HOSTNAME_GTW01 }}: +94
             default_{{ HOSTNAME_PRX01 }}: +121
           ip_ranges:
             dhcp: [+90, -10]
diff --git a/tcp_tests/templates/virtual-mcp11-k8s-calico-minimal/underlay.yaml b/tcp_tests/templates/virtual-mcp11-k8s-calico-minimal/underlay.yaml
index f494419..805a05f 100644
--- a/tcp_tests/templates/virtual-mcp11-k8s-calico-minimal/underlay.yaml
+++ b/tcp_tests/templates/virtual-mcp11-k8s-calico-minimal/underlay.yaml
@@ -128,7 +128,7 @@
                     - private
 
           - name: {{ HOSTNAME_CTL01 }}
-            role: salt_minion
+            role: k8s_controller
             params:
               vcpu: !os_env SLAVE_NODE_CPU, 2
               memory: !os_env SLAVE_NODE_MEMORY, 4096
diff --git a/tcp_tests/templates/virtual-mcp11-k8s-calico/underlay.yaml b/tcp_tests/templates/virtual-mcp11-k8s-calico/underlay.yaml
index d5bbb3a..658660c 100644
--- a/tcp_tests/templates/virtual-mcp11-k8s-calico/underlay.yaml
+++ b/tcp_tests/templates/virtual-mcp11-k8s-calico/underlay.yaml
@@ -45,7 +45,7 @@
             default_{{ HOSTNAME_MON01 }}: +107
             default_{{ HOSTNAME_MON02 }}: +108
             default_{{ HOSTNAME_MON03 }}: +109
-            default_{{ HOSTNAME_PRX01 }}: +110
+            default_{{ HOSTNAME_PRX01 }}: +121
           ip_ranges:
             dhcp: [+90, -10]
 
@@ -64,7 +64,7 @@
             default_{{ HOSTNAME_MON01 }}: +107
             default_{{ HOSTNAME_MON02 }}: +108
             default_{{ HOSTNAME_MON03 }}: +109
-            default_{{ HOSTNAME_PRX01 }}: +110
+            default_{{ HOSTNAME_PRX01 }}: +121
           ip_ranges:
             dhcp: [+90, -10]
 
@@ -142,7 +142,7 @@
                     - private
 
           - name: {{ HOSTNAME_CTL01 }}
-            role: salt_minion
+            role: k8s_controller
             params:
               vcpu: !os_env SLAVE_NODE_CPU, 2
               memory: !os_env SLAVE_NODE_MEMORY, 2048
diff --git a/tcp_tests/templates/virtual-mcp11-k8s-contrail/underlay.yaml b/tcp_tests/templates/virtual-mcp11-k8s-contrail/underlay.yaml
index 240b50b..786fea0 100644
--- a/tcp_tests/templates/virtual-mcp11-k8s-contrail/underlay.yaml
+++ b/tcp_tests/templates/virtual-mcp11-k8s-contrail/underlay.yaml
@@ -199,7 +199,7 @@
                     - admin
 
           - name: {{ HOSTNAME_CTL01 }}
-            role: salt_minion
+            role: k8s_controller
             params:
               vcpu: !os_env SLAVE_NODE_CPU, 2
               memory: !os_env SLAVE_NODE_MEMORY, 2048
diff --git a/tcp_tests/templates/virtual-mcp11-ovs/salt.yaml b/tcp_tests/templates/virtual-mcp11-ovs/salt.yaml
index 3c1cb55..f4fab6a 100644
--- a/tcp_tests/templates/virtual-mcp11-ovs/salt.yaml
+++ b/tcp_tests/templates/virtual-mcp11-ovs/salt.yaml
@@ -21,20 +21,26 @@
 
 {{ SHARED.MACRO_BOOTSTRAP_ALL_MINIONS() }}
 
+- description: WR run linux state to fix hosts
+  cmd: salt "cfg*" state.sls linux
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 10}
+  skip_fail: true
+
 - description: Hack gtw node
-  cmd: salt 'gtw*' cmd.run "ip addr del {{ SHARED.IPV4_NET_CONTROL_PREFIX }}.110/24 dev ens4; ip addr flush dev ens4";
+  cmd: salt 'gtw*' cmd.run "ip addr del {{ SHARED.IPV4_NET_CONTROL_PREFIX }}.94/24 dev ens4; ip addr flush dev ens4";
   node_name: {{ HOSTNAME_CFG01 }}
   retry: {count: 1, delay: 10}
   skip_fail: false
 
 - description: Hack cmp01 node
-  cmd: salt 'cmp01*' cmd.run "ip addr del {{ SHARED.IPV4_NET_CONTROL_PREFIX }}.105/24 dev ens4; ip addr flush dev ens4";
+  cmd: salt 'cmp01*' cmd.run "ip addr del {{ SHARED.IPV4_NET_CONTROL_PREFIX }}.95/24 dev ens4; ip addr flush dev ens4";
   node_name: {{ HOSTNAME_CFG01 }}
   retry: {count: 1, delay: 10}
   skip_fail: false
 
 - description: Hack cmp02 node
-  cmd: salt 'cmp02*' cmd.run "ip addr del {{ SHARED.IPV4_NET_CONTROL_PREFIX }}.106/24 dev ens4; ip addr flush dev ens4";
+  cmd: salt 'cmp02*' cmd.run "ip addr del {{ SHARED.IPV4_NET_CONTROL_PREFIX }}.96/24 dev ens4; ip addr flush dev ens4";
   node_name: {{ HOSTNAME_CFG01 }}
   retry: {count: 1, delay: 10}
   skip_fail: false
diff --git a/tcp_tests/templates/virtual-mcp11-ovs/underlay.yaml b/tcp_tests/templates/virtual-mcp11-ovs/underlay.yaml
index abdbab7..a7d88ff 100644
--- a/tcp_tests/templates/virtual-mcp11-ovs/underlay.yaml
+++ b/tcp_tests/templates/virtual-mcp11-ovs/underlay.yaml
@@ -34,13 +34,13 @@
           ip_reserved:
             gateway: +1
             l2_network_device: +1
-            default_{{ HOSTNAME_CFG01 }}: +100
-            default_{{ HOSTNAME_CTL01 }}: +101
-            default_{{ HOSTNAME_CTL02 }}: +102
-            default_{{ HOSTNAME_CTL03 }}: +103
-            default_{{ HOSTNAME_CMP01 }}: +105
-            default_{{ HOSTNAME_CMP02 }}: +106
-            default_{{ HOSTNAME_GTW01 }}: +110
+            default_{{ HOSTNAME_CFG01 }}: +90
+            default_{{ HOSTNAME_CTL01 }}: +91
+            default_{{ HOSTNAME_CTL02 }}: +92
+            default_{{ HOSTNAME_CTL03 }}: +93
+            default_{{ HOSTNAME_CMP01 }}: +95
+            default_{{ HOSTNAME_CMP02 }}: +96
+            default_{{ HOSTNAME_GTW01 }}: +94
             default_{{ HOSTNAME_PRX01 }}: +121
           ip_ranges:
             dhcp: [+90, -10]
@@ -52,12 +52,12 @@
             gateway: +1
             l2_network_device: +1
             default_{{ HOSTNAME_CFG01 }}: +90
-            default_{{ HOSTNAME_CTL01 }}: +101
-            default_{{ HOSTNAME_CTL02 }}: +102
-            default_{{ HOSTNAME_CTL03 }}: +103
-            default_{{ HOSTNAME_CMP01 }}: +105
-            default_{{ HOSTNAME_CMP02 }}: +106
-            default_{{ HOSTNAME_GTW01 }}: +110
+            default_{{ HOSTNAME_CTL01 }}: +91
+            default_{{ HOSTNAME_CTL02 }}: +92
+            default_{{ HOSTNAME_CTL03 }}: +93
+            default_{{ HOSTNAME_CMP01 }}: +95
+            default_{{ HOSTNAME_CMP02 }}: +96
+            default_{{ HOSTNAME_GTW01 }}: +94
             default_{{ HOSTNAME_PRX01 }}: +121
           ip_ranges:
             dhcp: [+90, -10]
diff --git a/tcp_tests/tests/environment/test_local_dns.py b/tcp_tests/tests/environment/test_local_dns.py
new file mode 100644
index 0000000..fcc0978
--- /dev/null
+++ b/tcp_tests/tests/environment/test_local_dns.py
@@ -0,0 +1,27 @@
+#    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 pytest
+
+from tcp_tests import logger
+
+LOG = logger.logger
+
+
+class TestLocalDns(object):
+    """Test class for deploy local dns_vm"""
+
+    @pytest.mark.fail_snapshot
+    def test_install_local_dns(self, config, underlay):
+        LOG.info("*************** DONE **************")
diff --git a/tcp_tests/tests/system/test_install_cookied_ocata.py b/tcp_tests/tests/system/test_install_cookied_ocata.py
index 125168d..3f3f208 100644
--- a/tcp_tests/tests/system/test_install_cookied_ocata.py
+++ b/tcp_tests/tests/system/test_install_cookied_ocata.py
@@ -23,6 +23,7 @@
 class Test_Mcp11_install(object):
     """Test class for testing mcp11 vxlan deploy"""
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_cookied_ocata_ovs_install(self, underlay, openstack_deployed,
                                        show_step):
@@ -35,6 +36,7 @@
         """
         LOG.info("*************** DONE **************")
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_cookied_ocata_dvr_install(self, underlay, openstack_deployed,
                                        show_step):
@@ -47,6 +49,7 @@
         """
         LOG.info("*************** DONE **************")
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_cookied_ocata_cicd_oss_install(self, underlay, oss_deployed,
                                             openstack_deployed, sl_deployed,
diff --git a/tcp_tests/tests/system/test_install_k8s.py b/tcp_tests/tests/system/test_install_k8s.py
index 6c926d8..7109497 100644
--- a/tcp_tests/tests/system/test_install_k8s.py
+++ b/tcp_tests/tests/system/test_install_k8s.py
@@ -24,6 +24,7 @@
 class Testk8sInstall(object):
     """Test class for testing Kubernetes deploy"""
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     @pytest.mark.cz8116
     def test_k8s_install_calico(self, config, show_step,
@@ -126,6 +127,7 @@
             k8s_actions.run_conformance()
         LOG.info("*************** DONE **************")
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     @pytest.mark.cz8115
     def test_k8s_install_contrail(self, config, show_step,
@@ -186,6 +188,7 @@
             k8s_actions.run_conformance()
         LOG.info("*************** DONE **************")
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_only_k8s_install(self, config, k8s_deployed, k8s_actions):
         """Test for deploying MCP environment with k8s and check it
diff --git a/tcp_tests/tests/system/test_install_mcp11_ovs_newton.py b/tcp_tests/tests/system/test_install_mcp11_ovs_newton.py
index 99f96e2..9235edb 100644
--- a/tcp_tests/tests/system/test_install_mcp11_ovs_newton.py
+++ b/tcp_tests/tests/system/test_install_mcp11_ovs_newton.py
@@ -24,6 +24,7 @@
 class TestMcp11Install(object):
     """Test class for testing mcp11 vxlan deploy"""
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_mcp11_newton_ovs_install(self, underlay, openstack_deployed,
                                       openstack_actions, show_step):
@@ -45,6 +46,7 @@
 
         LOG.info("*************** DONE **************")
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_mcp11_newton_dvr_install(self, underlay, openstack_deployed,
                                       openstack_actions, show_step):
diff --git a/tcp_tests/tests/system/test_install_mcp11_ovs_ocata.py b/tcp_tests/tests/system/test_install_mcp11_ovs_ocata.py
index 7f2daf5..9579139 100644
--- a/tcp_tests/tests/system/test_install_mcp11_ovs_ocata.py
+++ b/tcp_tests/tests/system/test_install_mcp11_ovs_ocata.py
@@ -24,6 +24,7 @@
 class Test_Mcp11_install(object):
     """Test class for testing mcp11 vxlan deploy"""
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     @pytest.mark.cz8119
     def test_mcp11_ocata_ovs_install(self, underlay,
@@ -46,6 +47,7 @@
             openstack_actions.download_tempest_report()
         LOG.info("*************** DONE **************")
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     @pytest.mark.cz8119
     def test_mcp11_ocata_ovs_sl_install(self, underlay, config,
@@ -80,6 +82,7 @@
             '/root/stacklight-pytest/stacklight_tests/report.xml')
         LOG.info("*************** DONE **************")
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     @pytest.mark.cz8120
     def test_mcp11_ocata_dvr_install(self,
@@ -102,6 +105,7 @@
             openstack_actions.download_tempest_report()
         LOG.info("*************** DONE **************")
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     @pytest.mark.cz8120
     def test_mcp11_ocata_dvr_sl_install(self, underlay, config,
diff --git a/tcp_tests/tests/system/test_k8s_actions.py b/tcp_tests/tests/system/test_k8s_actions.py
index 77ed04a..d7ee5a1 100644
--- a/tcp_tests/tests/system/test_k8s_actions.py
+++ b/tcp_tests/tests/system/test_k8s_actions.py
@@ -23,6 +23,7 @@
 class TestMCPK8sActions(object):
     """Test class for different k8s actions"""
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_k8s_externaldns_coredns(self, show_step, config, k8s_deployed):
         """Test externaldns integration with coredns
@@ -50,7 +51,7 @@
         show_step(3)
         k8s_deployed.kubectl_expose('deployment', name, '80', 'ClusterIP')
 
-        hostname = "test.{0}.local".format(settings.LAB_CONFIG_NAME)
+        hostname = "test.{0}.local.".format(settings.LAB_CONFIG_NAME)
         annotation = "\"external-dns.alpha.kubernetes.io/" \
                      "hostname={0}\"".format(hostname)
         show_step(4)
diff --git a/tcp_tests/tests/system/test_openstack_service_policy.py b/tcp_tests/tests/system/test_openstack_service_policy.py
index bf1ebb1..3b0e611 100644
--- a/tcp_tests/tests/system/test_openstack_service_policy.py
+++ b/tcp_tests/tests/system/test_openstack_service_policy.py
@@ -243,6 +243,7 @@
     """Test class for testing OpenStack services policy"""
 
     # https://github.com/salt-formulas/salt-formula-nova/pull/17 - Merged
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_policy_for_nova(self, underlay, openstack_deployed, salt_actions,
                              show_step):
@@ -264,6 +265,7 @@
         LOG.info("*************** DONE **************")
 
     # https://github.com/salt-formulas/salt-formula-cinder/pull/13 - Merged
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_policy_for_cinder(self, underlay, openstack_deployed,
                                salt_actions, show_step):
@@ -289,6 +291,7 @@
         LOG.info("*************** DONE **************")
 
     # https://github.com/salt-formulas/salt-formula-heat/pull/5 - Merged
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_policy_for_heat(self, underlay, openstack_deployed, salt_actions,
                              show_step):
@@ -314,6 +317,7 @@
         LOG.info("*************** DONE **************")
 
     # https://github.com/salt-formulas/salt-formula-glance/pull/9 - Merged
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_policy_for_glance(self, underlay, openstack_deployed,
                                salt_actions, show_step):
@@ -339,6 +343,7 @@
         LOG.info("*************** DONE **************")
 
     # https://github.com/salt-formulas/salt-formula-ceilometer/pull/2 - Merged
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     @pytest.mark.skip(reason="Skipped due no have ceilometer in environment")
     def test_policy_for_ceilometer(self, underlay, openstack_deployed,
@@ -365,6 +370,7 @@
         LOG.info("*************** DONE **************")
 
     # https://github.com/salt-formulas/salt-formula-neutron/pull/8 - Merged
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_policy_for_neutron(self, underlay, openstack_deployed,
                                 salt_actions, show_step):
@@ -390,6 +396,7 @@
         LOG.info("*************** DONE **************")
 
     # https://github.com/salt-formulas/salt-formula-keystone/pull/11 - Merged
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_policy_for_keystone(self, underlay, openstack_deployed,
                                  salt_actions, show_step):
diff --git a/tcp_tests/tests/system/test_oss_install.py b/tcp_tests/tests/system/test_oss_install.py
index ec6a6fb..f62f1c8 100644
--- a/tcp_tests/tests/system/test_oss_install.py
+++ b/tcp_tests/tests/system/test_oss_install.py
@@ -22,6 +22,7 @@
 class TestOSSInstaller(object):
     """Test class for testing Operational Support System Tools deployment"""
 
+    @pytest.mark.grab_versions
     @pytest.mark.fail_snapshot
     def test_oss_install_default(self, underlay, show_step,
                                  oss_deployed, openstack_deployed,