Merge "Update virtlet to 0.8.0"
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/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/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/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/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 ae3fa89..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
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,