Hello community,

here is the log from the commit of package python3-ipa for openSUSE:Factory 
checked in at 2018-12-13 19:48:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python3-ipa (Old)
 and      /work/SRC/openSUSE:Factory/.python3-ipa.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python3-ipa"

Thu Dec 13 19:48:53 2018 rev:11 rq:657526 version:2.5.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python3-ipa/python3-ipa.changes  2018-12-11 
15:49:27.214099090 +0100
+++ /work/SRC/openSUSE:Factory/.python3-ipa.new.28833/python3-ipa.changes       
2018-12-13 19:48:53.900665722 +0100
@@ -1,0 +2,13 @@
+Wed Dec 12 02:06:50 UTC 2018 - Sean Marlow <[email protected]>
+
+- Remove ec2_types.patch.
+  + Switched to boto3 from libcloud. Patch no longer needed.
+- Update to v2.5.0 (2018-12-11)
+  + Switch EC2 provider back to boto3.
+  + Add note on installing SLES test suite.
+  + Add option allowing collect info about VM in cloud.
+  + With running instance don't cleanup.
+  + Systemd cleanup in distro.
+  + Process pytest errors in results. 
+
+-------------------------------------------------------------------

Old:
----
  ec2_types.patch
  python3-ipa-2.4.0.tar.gz

New:
----
  python3-ipa-2.5.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python3-ipa.spec ++++++
--- /var/tmp/diff_new_pack.x06kja/_old  2018-12-13 19:48:54.280665231 +0100
+++ /var/tmp/diff_new_pack.x06kja/_new  2018-12-13 19:48:54.288665221 +0100
@@ -18,14 +18,13 @@
 
 %bcond_without test
 Name:           python3-ipa
-Version:        2.4.0
+Version:        2.5.0
 Release:        0
 Summary:        Command line and API for testing custom images
 License:        GPL-3.0-or-later
 Group:          Development/Languages/Python
 URL:            https://github.com/SUSE/ipa
 Source:         
https://files.pythonhosted.org/packages/source/p/python3-ipa/%{name}-%{version}.tar.gz
-Patch1:         ec2_types.patch
 BuildRequires:  python3-devel
 BuildRequires:  python3-setuptools
 Requires:       python3-PyYAML
@@ -34,6 +33,7 @@
 Requires:       python3-azure-mgmt-compute
 Requires:       python3-azure-mgmt-network
 Requires:       python3-azure-mgmt-resource
+Requires:       python3-boto3
 Requires:       python3-certifi
 Requires:       python3-click
 Requires:       python3-cryptography
@@ -49,6 +49,7 @@
 BuildRequires:  python3-azure-mgmt-compute
 BuildRequires:  python3-azure-mgmt-network
 BuildRequires:  python3-azure-mgmt-resource
+BuildRequires:  python3-boto3
 BuildRequires:  python3-certifi
 BuildRequires:  python3-click
 BuildRequires:  python3-coverage
@@ -75,7 +76,6 @@
 
 %prep
 %setup -q
-%patch1 -p1
 
 %build
 python3 setup.py build

++++++ python3-ipa-2.4.0.tar.gz -> python3-ipa-2.5.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/CHANGES.md 
new/python3-ipa-2.5.0/CHANGES.md
--- old/python3-ipa-2.4.0/CHANGES.md    2018-12-07 01:07:28.000000000 +0100
+++ new/python3-ipa-2.5.0/CHANGES.md    2018-12-12 02:51:13.000000000 +0100
@@ -1,3 +1,19 @@
+v2.5.0 (2018-12-11)
+===================
+
+- Add note on installing SLES test suite.
+  [\#148](https://github.com/SUSE-Enceladus/ipa/pull/148)
+- Add option allowing collect info about VM in cloud.
+  [\#149](https://github.com/SUSE-Enceladus/ipa/pull/149)
+- With running instance don't cleanup.
+  [\#152](https://github.com/SUSE-Enceladus/ipa/pull/152)
+- Systemd cleanup in distro.
+  [\#153](https://github.com/SUSE-Enceladus/ipa/pull/153)
+- Process pytest errors in results.
+  [\#154](https://github.com/SUSE-Enceladus/ipa/pull/154)
+- Switch EC2 provider back to boto3.
+  [\#155](https://github.com/SUSE-Enceladus/ipa/pull/155)
+
 v2.4.0 (2018-12-06)
 ===================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/PKG-INFO 
new/python3-ipa-2.5.0/PKG-INFO
--- old/python3-ipa-2.4.0/PKG-INFO      2018-12-07 01:08:23.000000000 +0100
+++ new/python3-ipa-2.5.0/PKG-INFO      2018-12-12 02:52:08.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: python3-ipa
-Version: 2.4.0
+Version: 2.5.0
 Summary: Package for automated testing of cloud images.
 Home-page: https://github.com/SUSE-Enceladus/ipa
 Author: SUSE
@@ -151,6 +151,6 @@
 Classifier: Programming Language :: Python :: 3.7
 Requires-Python: >=3.4
 Description-Content-Type: text/markdown
+Provides-Extra: dev
 Provides-Extra: test
 Provides-Extra: tox
-Provides-Extra: dev
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/ipa/__init__.py 
new/python3-ipa-2.5.0/ipa/__init__.py
--- old/python3-ipa-2.4.0/ipa/__init__.py       2018-12-07 01:07:28.000000000 
+0100
+++ new/python3-ipa-2.5.0/ipa/__init__.py       2018-12-12 02:51:14.000000000 
+0100
@@ -22,4 +22,4 @@
 
 __author__ = """SUSE"""
 __email__ = '[email protected]'
-__version__ = '2.4.0'
+__version__ = '2.5.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/ipa/ipa_azure.py 
new/python3-ipa-2.5.0/ipa/ipa_azure.py
--- old/python3-ipa-2.4.0/ipa/ipa_azure.py      2018-12-07 01:07:28.000000000 
+0100
+++ new/python3-ipa-2.5.0/ipa/ipa_azure.py      2018-12-12 02:51:14.000000000 
+0100
@@ -67,7 +67,8 @@
                  test_files=None,
                  timeout=None,
                  vnet_name=None,
-                 vnet_resource_group=None):
+                 vnet_resource_group=None,
+                 collect_vm_info=None):
         """Initialize Azure Provider class."""
         super(AzureProvider, self).__init__('azure',
                                             cleanup,
@@ -87,7 +88,8 @@
                                             running_instance_id,
                                             test_dirs,
                                             test_files,
-                                            timeout)
+                                            timeout,
+                                            collect_vm_info)
 
         if subnet_id and not (vnet_name and vnet_resource_group):
             raise AzureProviderException(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/ipa/ipa_controller.py 
new/python3-ipa-2.5.0/ipa/ipa_controller.py
--- old/python3-ipa-2.4.0/ipa/ipa_controller.py 2018-12-07 01:07:28.000000000 
+0100
+++ new/python3-ipa-2.5.0/ipa/ipa_controller.py 2018-12-12 02:51:14.000000000 
+0100
@@ -65,7 +65,8 @@
                tests=None,
                timeout=None,
                vnet_name=None,
-               vnet_resource_group=None):
+               vnet_resource_group=None,
+               collect_vm_info=None):
     """Creates a cloud provider instance and initiates testing."""
     provider_name = provider_name.lower()
     if provider_name == 'azure':
@@ -112,7 +113,8 @@
         test_files=tests,
         timeout=timeout,
         vnet_name=vnet_name,
-        vnet_resource_group=vnet_resource_group
+        vnet_resource_group=vnet_resource_group,
+        collect_vm_info=collect_vm_info
     )
 
     return provider.test_image()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/ipa/ipa_distro.py 
new/python3-ipa-2.5.0/ipa/ipa_distro.py
--- old/python3-ipa-2.4.0/ipa/ipa_distro.py     2018-12-07 01:07:28.000000000 
+0100
+++ new/python3-ipa-2.5.0/ipa/ipa_distro.py     2018-12-12 02:51:14.000000000 
+0100
@@ -35,7 +35,19 @@
 
     def _set_init_system(self, client):
         """Determine the init system of distribution."""
-        raise NotImplementedError(NOT_IMPLEMENTED)
+        if not self.init_system:
+            try:
+                out = ipa_utils.execute_ssh_command(
+                    client,
+                    'ps -p 1 -o comm='
+                )
+            except Exception as e:
+                raise IpaDistroException(
+                    'An error occurred while retrieving'
+                    ' the distro init system: %s' % e
+                )
+            if out:
+                self.init_system = out.strip()
 
     def get_install_cmd(self):
         """Return install package command for distribution."""
@@ -61,6 +73,35 @@
         """Return command to update instance."""
         raise NotImplementedError(NOT_IMPLEMENTED)
 
+    def get_vm_info(self, client):
+        """Return vm info."""
+        out = ''
+        self._set_init_system(client)
+
+        if self.init_system == 'systemd':
+            try:
+                out += 'systemd-analyze:\n\n'
+                out += ipa_utils.execute_ssh_command(
+                    client,
+                    'systemd-analyze'
+                )
+
+                out += 'systemd-analyze blame:\n\n'
+                out += ipa_utils.execute_ssh_command(
+                    client,
+                    'systemd-analyze blame'
+                )
+
+                out += 'journalctl -b:\n\n'
+                out += ipa_utils.execute_ssh_command(
+                    client,
+                    'sudo journalctl -b'
+                )
+            except Exception as error:
+                out = 'Failed to collect VM info: {0}.'.format(error)
+
+        return out
+
     def install_package(self, client, package):
         """Install package on instance."""
         install_cmd = "{sudo} '{install} {package}'".format(
@@ -87,8 +128,7 @@
 
     def reboot(self, client):
         """Execute reboot command on instance."""
-        if not self.init_system:
-            self._set_init_system(client)
+        self._set_init_system(client)
 
         reboot_cmd = "{sudo} '{stop_ssh};{reboot}'".format(
             sudo=self.get_sudo_exec_wrapper(),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/ipa/ipa_ec2.py 
new/python3-ipa-2.5.0/ipa/ipa_ec2.py
--- old/python3-ipa-2.4.0/ipa/ipa_ec2.py        2018-12-07 01:07:28.000000000 
+0100
+++ new/python3-ipa-2.5.0/ipa/ipa_ec2.py        2018-12-12 02:51:14.000000000 
+0100
@@ -2,7 +2,7 @@
 
 """Provider module for testing AWS EC2 images."""
 
-# Copyright (c) 2017 SUSE LLC
+# Copyright (c) 2018 SUSE LLC
 #
 # This file is part of ipa. Ipa provides an api and command line
 # utilities for testing images in the Public Cloud.
@@ -20,6 +20,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+import boto3
+
 from ipa import ipa_utils
 from ipa.ipa_constants import (
     BASH_SSH_SCRIPT,
@@ -28,14 +30,10 @@
     EC2_DEFAULT_USER
 )
 from ipa.ipa_exceptions import IpaException, EC2ProviderException
-from ipa.ipa_libcloud import LibcloudProvider
-
-from libcloud.common.exceptions import BaseHTTPError
-from libcloud.compute.types import Provider
-from libcloud.compute.providers import get_driver
+from ipa.ipa_provider import IpaProvider
 
 
-class EC2Provider(LibcloudProvider):
+class EC2Provider(IpaProvider):
     """Provider class for testing AWS EC2 images."""
 
     def __init__(self,
@@ -69,8 +67,8 @@
                  test_files=None,
                  timeout=None,
                  vnet_name=None,  # Not used in EC2
-                 vnet_resource_group=None  # Not used in EC2
-                 ):
+                 vnet_resource_group=None,  # Not used in EC2
+                 collect_vm_info=None):
         """Initialize EC2 provider class."""
         super(EC2Provider, self).__init__('ec2',
                                           cleanup,
@@ -90,7 +88,8 @@
                                           running_instance_id,
                                           test_dirs,
                                           test_files,
-                                          timeout)
+                                          timeout,
+                                          collect_vm_info)
         self.account_name = account_name
 
         if not self.account_name:
@@ -127,7 +126,9 @@
         )
         self.security_group_id = (
             security_group_id or
-            self._get_value('security_group_id')
+            self._get_value(
+                security_group_id, config_key='security_group_id'
+            )
         )
         self.ssh_key_name = (
             ssh_key_name or
@@ -152,26 +153,23 @@
                 'SSH private key file is required to connect to instance.'
             )
 
-        self.compute_driver = self._get_driver()
-
-    def _get_driver(self):
-        """Get authenticated EC2 driver."""
-        if not self.access_key_id:
-            raise EC2ProviderException(
-                'Access key id is required to authenticate EC2 driver.'
+    def _connect(self):
+        """Connect to ec2 resource."""
+        resource = None
+        try:
+            resource = boto3.resource(
+                'ec2',
+                aws_access_key_id=self.access_key_id,
+                aws_secret_access_key=self.secret_access_key,
+                region_name=self.region
             )
-
-        if not self.secret_access_key:
+            # boto3 resource is lazy so attempt method to test connection
+            resource.meta.client.describe_account_attributes()
+        except Exception:
             raise EC2ProviderException(
-                'Secret access key is required to authenticate EC2 driver.'
+                'Could not connect to region: %s' % self.region
             )
-
-        ComputeEngine = get_driver(Provider.EC2)
-        return ComputeEngine(
-            self.access_key_id,
-            self.secret_access_key,
-            region=self.region
-        )
+        return resource
 
     def _get_from_ec2_config(self, entry):
         """Get config entry from ec2utils config file."""
@@ -185,28 +183,13 @@
         else:
             return None
 
-    def _get_image(self):
-        """Retrieve NodeImage given the image id."""
-        try:
-            image = self.compute_driver.list_images(
-                ex_image_ids=[self.image_id]
-            )[0]
-        except (IndexError, BaseHTTPError):
-            raise EC2ProviderException(
-                'Image with ID: {image_id} not found.'.format(
-                    image_id=self.image_id
-                )
-            )
-
-        return image
-
     def _get_instance(self):
         """Retrieve instance matching instance_id."""
+        resource = self._connect()
+
         try:
-            instance = self.compute_driver.list_nodes(
-                ex_node_ids=[self.running_instance_id]
-            )[0]
-        except (IndexError, BaseHTTPError):
+            instance = resource.Instance(self.running_instance_id)
+        except Exception:
             raise EC2ProviderException(
                 'Instance with ID: {instance_id} not found.'.format(
                     instance_id=self.running_instance_id
@@ -214,36 +197,26 @@
             )
         return instance
 
-    def _get_instance_size(self):
-        """Retrieve NodeSize given the instance type."""
-        instance_type = self.instance_type or EC2_DEFAULT_TYPE
-
-        try:
-            sizes = self.compute_driver.list_sizes()
-            size = [size for size in sizes if size.id == instance_type][0]
-        except IndexError:
-            raise EC2ProviderException(
-                'Instance type: {instance_type} not found.'.format(
-                    instance_type=instance_type
-                )
-            )
-
-        return size
+    def _get_instance_state(self):
+        """
+        Attempt to retrieve the state of the instance.
+         Raises:
+            EC2ProviderException: If the instance cannot be found.
+        """
+        instance = self._get_instance()
+        state = None
 
-    def _get_subnet(self, subnet_id):
-        subnet = None
         try:
-            subnet = self.compute_driver.ex_list_subnets(
-                subnet_ids=[subnet_id]
-            )[0]
+            state = instance.state['Name']
         except Exception:
             raise EC2ProviderException(
-                'EC2 subnet: {subnet_id} not found.'.format(
-                    subnet_id=subnet_id
+                'Instance with id: {instance_id}, '
+                'cannot be found.'.format(
+                    instance_id=self.running_instance_id
                 )
             )
 
-        return subnet
+        return state
 
     def _get_user_data(self):
         """
@@ -258,34 +231,96 @@
         script = BASH_SSH_SCRIPT.format(user=self.ssh_user, key=key)
         return script
 
+    def _is_instance_running(self):
+        """
+        Return True if instance is in running state.
+        """
+        return self._get_instance_state() == 'running'
+
     def _launch_instance(self):
         """Launch an instance of the given image."""
+        resource = self._connect()
+
+        instance_name = ipa_utils.generate_instance_name('ec2-ipa-test')
         kwargs = {
-            'name': ipa_utils.generate_instance_name('ec2-ipa-test'),
-            'size': self._get_instance_size(),
-            'image': self._get_image()
+            'InstanceType': self.instance_type or EC2_DEFAULT_TYPE,
+            'ImageId': self.image_id,
+            'MaxCount': 1,
+            'MinCount': 1,
+            'TagSpecifications': [
+                {
+                    'ResourceType': 'instance',
+                    'Tags': [
+                        {
+                            'Key': 'Name',
+                            'Value': instance_name
+                        }
+                    ]
+                }
+            ]
         }
 
         if self.ssh_key_name:
-            kwargs['ex_keyname'] = self.ssh_key_name
+            kwargs['KeyName'] = self.ssh_key_name
         else:
-            kwargs['ex_userdata'] = self._get_user_data()
+            kwargs['UserData'] = self._get_user_data()
 
         if self.subnet_id:
-            kwargs['ex_subnet'] = self._get_subnet(self.subnet_id)
+            kwargs['SubnetId'] = self.subnet_id
 
         if self.security_group_id:
-            kwargs['ex_security_group_ids'] = [self.security_group_id]
+            kwargs['SecurityGroupIds'] = [self.security_group_id]
 
-        instance = self.compute_driver.create_node(**kwargs)
+        try:
+            instances = resource.create_instances(**kwargs)
+        except Exception as error:
+            raise EC2ProviderException(
+                'Unable to create instance: {0}.'.format(error)
+            )
 
-        self.compute_driver.wait_until_running(
-            [instance],
-            timeout=self.timeout
-        )
-        self.running_instance_id = instance.id
+        instances[0].wait_until_running()
+        self.running_instance_id = instances[0].instance_id
 
     def _set_image_id(self):
         """If existing image used get image id."""
         instance = self._get_instance()
-        self.image_id = instance.extra['image_id']
+        self.image_id = instance.image_id
+
+    def _set_instance_ip(self):
+        """
+        Retrieve instance ip and cache it.
+
+        Current preference is for public ipv4, ipv6 and private.
+        """
+        instance = self._get_instance()
+
+        # ipv6
+        try:
+            ipv6 = instance.network_interfaces[0].ipv6_addresses[0]
+        except IndexError:
+            ipv6 = None
+
+        self.instance_ip = instance.public_ip_address or \
+            ipv6 or instance.private_ip_address
+
+        if not self.instance_ip:
+            raise EC2ProviderException(
+                'IP address for instance cannot be found.'
+            )
+
+    def _start_instance(self):
+        """Start the instance."""
+        instance = self._get_instance()
+        instance.start()
+        instance.wait_until_running()
+
+    def _stop_instance(self):
+        """Stop the instance."""
+        instance = self._get_instance()
+        instance.stop()
+        instance.wait_until_stopped()
+
+    def _terminate_instance(self):
+        """Terminate the instance."""
+        instance = self._get_instance()
+        instance.terminate()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/ipa/ipa_gce.py 
new/python3-ipa-2.5.0/ipa/ipa_gce.py
--- old/python3-ipa-2.4.0/ipa/ipa_gce.py        2018-12-07 01:07:28.000000000 
+0100
+++ new/python3-ipa-2.5.0/ipa/ipa_gce.py        2018-12-12 02:51:14.000000000 
+0100
@@ -70,8 +70,8 @@
                  test_files=None,
                  timeout=None,
                  vnet_name=None,  # Not used in GCE
-                 vnet_resource_group=None  # Not used in GCE
-                 ):
+                 vnet_resource_group=None,  # Not used in GCE
+                 collect_vm_info=None):
         super(GCEProvider, self).__init__('gce',
                                           cleanup,
                                           config,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/ipa/ipa_provider.py 
new/python3-ipa-2.5.0/ipa/ipa_provider.py
--- old/python3-ipa-2.4.0/ipa/ipa_provider.py   2018-12-07 01:07:28.000000000 
+0100
+++ new/python3-ipa-2.5.0/ipa/ipa_provider.py   2018-12-12 02:51:14.000000000 
+0100
@@ -78,7 +78,8 @@
                  running_instance_id=None,
                  test_dirs=None,
                  test_files=None,
-                 timeout=None):
+                 timeout=None,
+                 collect_vm_info=None):
         """Initialize base provider class."""
         super(IpaProvider, self).__init__()
         log_level = log_level or logging.INFO
@@ -105,6 +106,11 @@
         self.host_key_fingerprint = None
         self.instance_ip = None
         self.provider = provider
+        self.collect_vm_info = self._get_value(
+            collect_vm_info,
+            config_key='collect_vm_info',
+            default=False
+        )
 
         self.cleanup = self._get_value(cleanup)
         self.distro_name = self._get_value(distro_name)
@@ -293,7 +299,7 @@
             self.test_files
         )
 
-    def _process_sync_test_results(self, duration, test_name, success=0):
+    def _process_test_results(self, duration, test_name, success=0):
         """Create result dict for sync test and merge with overall results."""
         status = 'passed' if success == 0 else 'failed'
         result = {
@@ -336,7 +342,14 @@
         cmds = shlex.split(args)
         plugin = Report()
         result = pytest.main(cmds, plugins=[plugin])
-        self._merge_results(plugin.report)
+
+        # If pytest has an error there will be no report but
+        # we still want to process the error as a failure.
+        # https://docs.pytest.org/en/latest/usage.html#possible-exit-codes
+        if result in (2, 3, 4):
+            self._process_test_results(0, 'pytest_error', 1)
+        else:
+            self._merge_results(plugin.report)
 
         return result
 
@@ -421,6 +434,19 @@
         """Terminate the instance."""
         raise NotImplementedError(NOT_IMPLEMENTED)
 
+    def _collect_vm_info(self):
+        """
+        Gather basic info about VM
+        """
+        self.logger.info('Collecting basic info about VM')
+        client = self._get_ssh_client()
+
+        out = self.distro.get_vm_info(client)
+
+        with open(self.log_file, 'a') as log_file:
+            log_file.write('\n')
+            log_file.write(out)
+
     def _update_history(self):
         """Save the current test information to history json."""
         ipa_utils.update_history_log(
@@ -607,6 +633,11 @@
             # Use existing instance
             self._start_instance_if_stopped()
             self._set_image_id()
+
+            # With a running instance default to no cleanup
+            # if a value has not been provided.
+            if self.cleanup is None:
+                self.cleanup = False
         else:
             # Launch new instance
             self.logger.info('Launching new instance')
@@ -671,7 +702,7 @@
                         break
                     finally:
                         duration = time.time() - start
-                        self._process_sync_test_results(
+                        self._process_test_results(
                             duration, 'test_hard_reboot', result
                         )
                         status = status or result
@@ -703,7 +734,7 @@
                         break
                     finally:
                         duration = time.time() - start
-                        self._process_sync_test_results(
+                        self._process_test_results(
                             duration, 'test_soft_reboot', result
                         )
                         status = status or result
@@ -724,7 +755,7 @@
                             log_file.write(out)
                     finally:
                         duration = time.time() - start
-                        self._process_sync_test_results(
+                        self._process_test_results(
                             duration, 'test_update', result
                         )
                         status = status or result
@@ -745,6 +776,10 @@
                 if status and self.early_exit:
                     break
 
+        # flag set to collect VM info
+        if self.collect_vm_info:
+            self._collect_vm_info()
+
         # If tests pass and cleanup flag is none, or
         # cleanup flag is true, terminate instance.
         if status == 0 and self.cleanup is None or self.cleanup:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/ipa/ipa_sles.py 
new/python3-ipa-2.5.0/ipa/ipa_sles.py
--- old/python3-ipa-2.4.0/ipa/ipa_sles.py       2018-12-07 01:07:28.000000000 
+0100
+++ new/python3-ipa-2.5.0/ipa/ipa_sles.py       2018-12-12 02:51:14.000000000 
+0100
@@ -20,7 +20,6 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from ipa import ipa_utils
 from ipa.ipa_distro import Distro
 from ipa.ipa_exceptions import IpaSLESException
 
@@ -28,21 +27,6 @@
 class SLES(Distro):
     """SLES distro class."""
 
-    def _set_init_system(self, client):
-        """Determine the init system of distribution."""
-        try:
-            out = ipa_utils.execute_ssh_command(
-                client,
-                'ps -p 1 -o comm='
-            )
-        except Exception as e:
-            raise IpaSLESException(
-                'An error occurred while retrieving'
-                ' the distro init system: %s' % e
-            )
-        if out:
-            self.init_system = out.strip()
-
     def get_install_cmd(self):
         """Return install package command for SLES."""
         return 'zypper -n --no-gpg-checks in -y'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/ipa/ipa_ssh.py 
new/python3-ipa-2.5.0/ipa/ipa_ssh.py
--- old/python3-ipa-2.4.0/ipa/ipa_ssh.py        2018-12-07 01:07:28.000000000 
+0100
+++ new/python3-ipa-2.5.0/ipa/ipa_ssh.py        2018-12-12 02:51:14.000000000 
+0100
@@ -59,8 +59,8 @@
                  test_files=None,
                  timeout=None,
                  vnet_name=None,  # Not used in SSH
-                 vnet_resource_group=None  # Not used in SSH
-                 ):
+                 vnet_resource_group=None,  # Not used in SSH
+                 collect_vm_info=None):
         """Initialize Azure Provider class."""
         super(SSHProvider, self).__init__('ssh',
                                           cleanup,
@@ -80,7 +80,8 @@
                                           running_instance_id,
                                           test_dirs,
                                           test_files,
-                                          timeout)
+                                          timeout,
+                                          collect_vm_info)
 
         # Cannot cleanup SSH instance
         self.cleanup = False
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/ipa/scripts/cli.py 
new/python3-ipa-2.5.0/ipa/scripts/cli.py
--- old/python3-ipa-2.4.0/ipa/scripts/cli.py    2018-12-07 01:07:28.000000000 
+0100
+++ new/python3-ipa-2.5.0/ipa/scripts/cli.py    2018-12-12 02:51:14.000000000 
+0100
@@ -238,6 +238,11 @@
     '--vnet-resource-group',
     help='Azure resource group name where virtual network is found.'
 )
[email protected](
+    '--collect-vm-info',
+    is_flag=True,
+    help='Controls whether general info about VM in cloud should be collected'
+)
 @click.argument(
     'provider',
     type=click.Choice(SUPPORTED_PROVIDERS)
@@ -275,6 +280,7 @@
          timeout,
          vnet_name,
          vnet_resource_group,
+         collect_vm_info,
          provider,
          tests):
     """Test image in the given framework using the supplied test files."""
@@ -312,7 +318,8 @@
             tests,
             timeout,
             vnet_name,
-            vnet_resource_group
+            vnet_resource_group,
+            collect_vm_info
         )
         echo_results(results, no_color)
         sys.exit(status)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/package/python3-ipa.spec 
new/python3-ipa-2.5.0/package/python3-ipa.spec
--- old/python3-ipa-2.4.0/package/python3-ipa.spec      2018-12-07 
01:07:28.000000000 +0100
+++ new/python3-ipa-2.5.0/package/python3-ipa.spec      2018-12-12 
02:51:14.000000000 +0100
@@ -18,7 +18,7 @@
 
 %bcond_without test
 Name:           python3-ipa
-Version:        2.4.0
+Version:        2.5.0
 Release:        0
 Summary:        Command line and API for testing custom images
 License:        GPL-3.0-or-later
@@ -28,6 +28,7 @@
 BuildRequires:  python3-devel
 BuildRequires:  python3-setuptools
 Requires:       python3-PyYAML
+Requires:       python3-boto3
 Requires:       python3-apache-libcloud
 Requires:       python3-azure-common
 Requires:       python3-azure-mgmt-compute
@@ -43,6 +44,7 @@
 BuildArch:      noarch
 %if %{with test}
 BuildRequires:  python3-PyYAML
+BuildRequires:  python3-boto3
 BuildRequires:  python3-apache-libcloud
 BuildRequires:  python3-azure-common
 BuildRequires:  python3-azure-mgmt-compute
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/python3_ipa.egg-info/PKG-INFO 
new/python3-ipa-2.5.0/python3_ipa.egg-info/PKG-INFO
--- old/python3-ipa-2.4.0/python3_ipa.egg-info/PKG-INFO 2018-12-07 
01:08:23.000000000 +0100
+++ new/python3-ipa-2.5.0/python3_ipa.egg-info/PKG-INFO 2018-12-12 
02:52:08.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: python3-ipa
-Version: 2.4.0
+Version: 2.5.0
 Summary: Package for automated testing of cloud images.
 Home-page: https://github.com/SUSE-Enceladus/ipa
 Author: SUSE
@@ -151,6 +151,6 @@
 Classifier: Programming Language :: Python :: 3.7
 Requires-Python: >=3.4
 Description-Content-Type: text/markdown
+Provides-Extra: dev
 Provides-Extra: test
 Provides-Extra: tox
-Provides-Extra: dev
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/python3_ipa.egg-info/requires.txt 
new/python3-ipa-2.5.0/python3_ipa.egg-info/requires.txt
--- old/python3-ipa-2.4.0/python3_ipa.egg-info/requires.txt     2018-12-07 
01:08:23.000000000 +0100
+++ new/python3-ipa-2.5.0/python3_ipa.egg-info/requires.txt     2018-12-12 
02:52:08.000000000 +0100
@@ -1,3 +1,4 @@
+boto3
 apache-libcloud
 azure-common
 azure-mgmt-compute
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/requirements.txt 
new/python3-ipa-2.5.0/requirements.txt
--- old/python3-ipa-2.4.0/requirements.txt      2018-12-07 01:07:28.000000000 
+0100
+++ new/python3-ipa-2.5.0/requirements.txt      2018-12-12 02:51:14.000000000 
+0100
@@ -1,3 +1,4 @@
+boto3
 apache-libcloud
 azure-common
 azure-mgmt-compute
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/setup.cfg 
new/python3-ipa-2.5.0/setup.cfg
--- old/python3-ipa-2.4.0/setup.cfg     2018-12-07 01:08:23.000000000 +0100
+++ new/python3-ipa-2.5.0/setup.cfg     2018-12-12 02:52:08.000000000 +0100
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 2.4.0
+current_version = 2.5.0
 commit = True
 tag = False
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/setup.py 
new/python3-ipa-2.5.0/setup.py
--- old/python3-ipa-2.4.0/setup.py      2018-12-07 01:07:28.000000000 +0100
+++ new/python3-ipa-2.5.0/setup.py      2018-12-12 02:51:14.000000000 +0100
@@ -43,7 +43,7 @@
 
 setup(
     name='python3-ipa',
-    version='2.4.0',
+    version='2.5.0',
     description="Package for automated testing of cloud images.",
     long_description=readme,
     long_description_content_type="text/markdown",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/tests/test_ipa_distro.py 
new/python3-ipa-2.5.0/tests/test_ipa_distro.py
--- old/python3-ipa-2.4.0/tests/test_ipa_distro.py      2018-12-07 
01:07:28.000000000 +0100
+++ new/python3-ipa-2.5.0/tests/test_ipa_distro.py      2018-12-12 
02:51:14.000000000 +0100
@@ -22,8 +22,9 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from ipa.ipa_distro import Distro
+from ipa.ipa_exceptions import IpaDistroException
 
-from unittest.mock import MagicMock
+from unittest.mock import call, MagicMock, patch
 
 import pytest
 
@@ -49,16 +50,20 @@
     )
 
 
-def test_distro_set_init_system():
-    """Test set init system raises not implemented exception."""
-    distro = Distro()
+def test_distro_set_init_system_exception():
+    """Test distro set init system method exception."""
     client = MagicMock()
+    distro = Distro()
 
-    pytest.raises(
-        NotImplementedError,
-        getattr(distro, '_set_init_system'),
-        client
-    )
+    with patch('ipa.ipa_utils.execute_ssh_command', MagicMock(
+               side_effect=Exception('ERROR!'))) as mocked:
+        pytest.raises(
+            IpaDistroException,
+            distro._set_init_system,
+            client
+        )
+
+    mocked.assert_called_once_with(client, 'ps -p 1 -o comm=')
 
 
 def test_distro_get_commands():
@@ -66,3 +71,20 @@
     distro = Distro()
     assert distro.get_reboot_cmd() == 'shutdown -r now'
     assert distro.get_sudo_exec_wrapper() == 'sudo sh -c'
+
+
+def test_distro_get_vm_info():
+    """Test distro get vm info method."""
+    client = MagicMock()
+    distro = Distro()
+    distro.init_system = 'systemd'
+
+    with patch('ipa.ipa_utils.execute_ssh_command',
+               MagicMock(return_value='')) as mocked:
+        distro.get_vm_info(client)
+
+    mocked.assert_has_calls([
+        call(client, 'systemd-analyze'),
+        call(client, 'systemd-analyze blame'),
+        call(client, 'sudo journalctl -b')
+    ])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/tests/test_ipa_ec2.py 
new/python3-ipa-2.5.0/tests/test_ipa_ec2.py
--- old/python3-ipa-2.4.0/tests/test_ipa_ec2.py 2018-12-07 01:07:28.000000000 
+0100
+++ new/python3-ipa-2.5.0/tests/test_ipa_ec2.py 2018-12-12 02:51:14.000000000 
+0100
@@ -3,7 +3,7 @@
 
 """Ipa ec2 provider unit tests."""
 
-# Copyright (c) 2017 SUSE LLC
+# Copyright (c) 2018 SUSE LLC
 #
 # This file is part of ipa. Ipa provides an api and command line
 # utilities for testing images in the Public Cloud.
@@ -21,6 +21,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+import boto3
 import pytest
 
 from ipa.ipa_ec2 import EC2Provider
@@ -41,7 +42,8 @@
             'image_id': 'fakeimage',
             'no_default_test_dirs': True,
             'provider_config': 'tests/ec2/.ec2utils.conf',
-            'test_files': ['test_image']
+            'test_files': ['test_image'],
+            'ssh_key_name': 'test-key'
         }
 
     def test_ec2_exception_required_args(self):
@@ -66,71 +68,89 @@
         assert str(error.value) == msg
         self.kwargs['provider_config'] = 'tests/ec2/.ec2utils.conf'
 
-    @patch('libcloud.compute.drivers.ec2.EC2NodeDriver')
-    def test_gce_get_driver(self, mock_node_driver):
-        """Test ec2 get driver method."""
-        driver = MagicMock()
-        mock_node_driver.return_value = driver
+    @patch.object(boto3, 'resource')
+    def test_ec2_bad_connection(self, mock_boto3):
+        """Test an exception is raised if boto3 unable to connect."""
+        mock_boto3.side_effect = Exception('ERROR!')
 
         provider = EC2Provider(**self.kwargs)
-        assert driver == provider.compute_driver
+        msg = 'Could not connect to region: %s' % provider.region
 
-    @patch.object(EC2Provider, '_get_driver')
-    def test_ec2_get_instance(self, mock_get_driver):
+        # Test ssh private key file required
+        with pytest.raises(EC2ProviderException) as error:
+            provider._connect()
+
+        assert str(error.value) == msg
+        assert mock_boto3.call_count > 0
+
+    @patch.object(EC2Provider, '_connect')
+    def test_ec2_get_instance(self, mock_connect):
         """Test get instance method."""
         instance = MagicMock()
-        driver = MagicMock()
-        mock_get_driver.return_value = driver
-        driver.list_nodes.return_value = [instance]
+        resource = MagicMock()
+        resource.Instance.return_value = instance
+        mock_connect.return_value = resource
 
         provider = EC2Provider(**self.kwargs)
         val = provider._get_instance()
         assert val == instance
-        assert driver.list_nodes.call_count == 1
+        assert mock_connect.call_count == 1
 
-    @patch.object(EC2Provider, '_get_driver')
-    def test_ec2_get_instance_not_found(self, mock_get_driver):
-        """Test get instance method."""
-        driver = MagicMock()
-        mock_get_driver.return_value = driver
-        driver.list_nodes.return_value = []
+    @patch.object(EC2Provider, '_connect')
+    def test_ec2_get_instance_error(self, mock_connect):
+        """Test get instance method error."""
+        resource = MagicMock()
+        resource.Instance.side_effect = Exception('Error!')
+        mock_connect.return_value = resource
 
-        self.kwargs['running_instance_id'] = 'i-123456789'
         provider = EC2Provider(**self.kwargs)
+        provider.running_instance_id = 'i-123456789'
 
         with pytest.raises(EC2ProviderException) as error:
             provider._get_instance()
 
-        assert str(error.value) == 'Instance with ID: i-123456789 not found.'
-        assert driver.list_nodes.call_count == 1
+        msg = 'Instance with ID: i-123456789 not found.'
+        assert str(error.value) == msg
 
-    @patch.object(EC2Provider, '_get_driver')
-    def test_ec2_get_subnet(self, mock_get_driver):
-        """Test EC2 get subnetwork method."""
-        subnetwork = MagicMock()
-        driver = MagicMock()
-        driver.ex_list_subnets.return_value = [subnetwork]
-        mock_get_driver.return_value = driver
+    @patch.object(EC2Provider, '_get_instance')
+    def test_ec2_get_instance_state(self, mock_get_instance):
+        """Test an exception is raised if boto3 unable to connect."""
+        instance = MagicMock()
+        instance.state = {'Name': 'ReadyRole'}
+        mock_get_instance.return_value = instance
 
         provider = EC2Provider(**self.kwargs)
-        result = provider._get_subnet('test-subnet')
+        val = provider._get_instance_state()
+        assert val == 'ReadyRole'
+        assert mock_get_instance.call_count == 1
+
+        instance.state = {}
+        mock_get_instance.reset_mock()
+        msg = 'Instance with id: %s, cannot be found.' \
+              % provider.running_instance_id
+
+        # Test exception raised if instance state not found
+        with pytest.raises(EC2ProviderException) as error:
+            provider._get_instance_state()
 
-        assert result == subnetwork
+        assert str(error.value) == msg
+        assert mock_get_instance.call_count == 1
 
-    @patch.object(EC2Provider, '_get_driver')
-    def test_ec2_get_subnet_exception(self, mock_get_driver):
-        """Test EC2 get subnetwork method."""
-        driver = MagicMock()
-        driver.ex_list_subnets.side_effect = Exception('Cannot find subnet!')
-        mock_get_driver.return_value = driver
+    @patch.object(EC2Provider, '_get_instance_state')
+    def test_ec2_is_instance_running(self, mock_get_instance_state):
+        """Test ec2 provider is instance runnning method."""
+        mock_get_instance_state.return_value = 'running'
 
         provider = EC2Provider(**self.kwargs)
+        assert provider._is_instance_running()
+        assert mock_get_instance_state.call_count == 1
 
-        msg = 'EC2 subnet: test-subnet not found.'
-        with pytest.raises(EC2ProviderException) as error:
-            provider._get_subnet('test-subnet')
+        mock_get_instance_state.return_value = 'stopped'
+        mock_get_instance_state.reset_mock()
 
-        assert msg == str(error.value)
+        provider = EC2Provider(**self.kwargs)
+        assert not provider._is_instance_running()
+        assert mock_get_instance_state.call_count == 1
 
     @patch('ipa.ipa_ec2.ipa_utils.generate_public_ssh_key')
     def test_ec2_get_user_data(self, mock_generate_ssh_key):
@@ -143,87 +163,111 @@
         assert result == '#!/bin/bash\n' \
             'echo testkey12345 >> /home/ec2-user/.ssh/authorized_keys\n'
 
-    @patch.object(EC2Provider, '_get_user_data')
-    @patch.object(EC2Provider, '_get_subnet')
-    @patch.object(EC2Provider, '_get_driver')
-    def test_ec2_launch_instance(
-        self, mock_get_driver, mock_get_subnet, mock_get_user_data
-    ):
+    @patch.object(EC2Provider, '_connect')
+    def test_ec2_launch_instance(self, mock_connect):
         """Test ec2 provider launch instance method."""
-        driver = MagicMock()
+        instance = MagicMock()
+        instance.instance_id = 'i-123456789'
+        instances = [instance]
 
-        size = MagicMock()
-        size.id = 't2.micro'
-        driver.list_sizes.return_value = [size]
+        resource = MagicMock()
+        resource.create_instances.return_value = instances
 
-        image = MagicMock()
-        image.id = 'fakeimage'
-        driver.list_images.return_value = [image]
+        mock_connect.return_value = resource
 
-        instance = MagicMock()
-        instance.id = 'i-123456789'
-        driver.create_node.return_value = instance
+        provider = EC2Provider(**self.kwargs)
+        provider.subnet_id = 'subnet-123456789'
+        provider.security_group_id = 'sg-123456789'
+        provider._launch_instance()
 
-        mock_get_driver.return_value = driver
+        assert instance.instance_id == provider.running_instance_id
+        assert resource.create_instances.call_count == 1
 
-        subnet = MagicMock()
-        mock_get_subnet.return_value = subnet
+    @patch.object(EC2Provider, '_get_instance')
+    def test_ec2_set_image_id(self, mock_get_instance):
+        """Test ec2 provider set image id method."""
+        instance = MagicMock()
+        instance.image_id = 'ami-123456'
+        mock_get_instance.return_value = instance
 
         provider = EC2Provider(**self.kwargs)
-        provider.subnet_id = 'test-subnet'
-        provider._launch_instance()
+        provider._set_image_id()
 
-        assert instance.id == provider.running_instance_id
-        assert driver.list_sizes.call_count == 1
-        assert driver.list_images.call_count == 1
-        assert driver.create_node.call_count == 1
+        assert provider.image_id == instance.image_id
+        assert mock_get_instance.call_count == 1
 
-    @patch.object(EC2Provider, '_get_driver')
-    def test_ec2_launch_instance_no_size(self, mock_get_driver):
-        """Test exception raised if instance type not found."""
-        driver = MagicMock()
-        driver.list_sizes.return_value = []
+    @patch.object(EC2Provider, '_get_instance')
+    def test_ec2_set_instance_ip(self, mock_get_instance):
+        """Test ec2 provider set image id method."""
+        instance = MagicMock()
+        instance.public_ip_address = None
+        instance.private_ip_address = None
+        instance.network_interfaces = []
+        mock_get_instance.return_value = instance
 
-        mock_get_driver.return_value = driver
         provider = EC2Provider(**self.kwargs)
+        msg = 'IP address for instance cannot be found.'
 
         with pytest.raises(EC2ProviderException) as error:
-            provider._launch_instance()
+            provider._set_instance_ip()
+
+        assert str(error.value) == msg
+        assert mock_get_instance.call_count == 1
+        mock_get_instance.reset_mock()
 
-        assert str(error.value) == 'Instance type: t2.micro not found.'
-        assert driver.list_sizes.call_count == 1
+        instance.private_ip_address = '127.0.0.1'
 
-    @patch.object(EC2Provider, '_get_driver')
-    def test_ec2_launch_instance_no_image(self, mock_get_driver):
-        """Test exception raised if image not found."""
-        driver = MagicMock()
+        provider._set_instance_ip()
+        assert provider.instance_ip == '127.0.0.1'
+        assert mock_get_instance.call_count == 1
+        mock_get_instance.reset_mock()
 
-        size = MagicMock()
-        size.id = 't2.micro'
-        driver.list_sizes.return_value = [size]
-        driver.list_images.return_value = []
+        network_interface = MagicMock()
+        network_interface.ipv6_addresses = ['127.0.0.2']
+        instance.network_interfaces = [network_interface]
 
-        mock_get_driver.return_value = driver
-        provider = EC2Provider(**self.kwargs)
+        provider._set_instance_ip()
+        assert provider.instance_ip == '127.0.0.2'
+        assert mock_get_instance.call_count == 1
+        mock_get_instance.reset_mock()
 
-        with pytest.raises(EC2ProviderException) as error:
-            provider._launch_instance()
+        instance.public_ip_address = '127.0.0.3'
 
-        assert str(error.value) == 'Image with ID: fakeimage not found.'
-        assert driver.list_sizes.call_count == 1
-        assert driver.list_images.call_count == 1
+        provider._set_instance_ip()
+        assert provider.instance_ip == '127.0.0.3'
+        assert mock_get_instance.call_count == 1
 
     @patch.object(EC2Provider, '_get_instance')
-    @patch.object(EC2Provider, '_get_driver')
-    def test_ec2_set_image_id(self, mock_get_driver, mock_get_instance):
-        """Test ec2 provider set image id method."""
+    def test_ec2_start_instance(self, mock_get_instance):
+        """Test ec2 start instance method."""
         instance = MagicMock()
-        instance.extra = {'image_id': 'ami-123456'}
+        instance.start.return_value = None
+        instance.wait_until_running.return_value = None
         mock_get_instance.return_value = instance
-        mock_get_driver.return_value = None
 
         provider = EC2Provider(**self.kwargs)
-        provider._set_image_id()
+        provider._start_instance()
+        assert mock_get_instance.call_count == 1
+
+    @patch.object(EC2Provider, '_get_instance')
+    def test_ec2_stop_instance(self, mock_get_instance):
+        """Test ec2 stop instance method."""
+        instance = MagicMock()
+        instance.stop.return_value = None
+        instance.wait_until_stopped.return_value = None
+        mock_get_instance.return_value = instance
+
+        provider = EC2Provider(**self.kwargs)
+        provider._stop_instance()
+        assert mock_get_instance.call_count == 1
 
-        assert provider.image_id == instance.extra['image_id']
+    @patch.object(EC2Provider, '_get_instance')
+    def test_ec2_terminate_instance(self, mock_get_instance):
+        """Test ec2 terminate instance method."""
+        instance = MagicMock()
+        instance.terminate.return_value = None
+        mock_get_instance.return_value = instance
+
+        provider = EC2Provider(**self.kwargs)
+        provider._terminate_instance()
         assert mock_get_instance.call_count == 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/tests/test_ipa_provider.py 
new/python3-ipa-2.5.0/tests/test_ipa_provider.py
--- old/python3-ipa-2.4.0/tests/test_ipa_provider.py    2018-12-07 
01:07:28.000000000 +0100
+++ new/python3-ipa-2.5.0/tests/test_ipa_provider.py    2018-12-12 
02:51:14.000000000 +0100
@@ -188,9 +188,9 @@
         for key, val in results['tests'][0].items():
             assert provider.results['tests'][0][key] == val
 
-    def test_process_sync_test_results(self):
+    def test_process_test_results(self):
         provider = IpaProvider(*args, **self.kwargs)
-        provider._process_sync_test_results(5.0, 'test_test')
+        provider._process_test_results(5.0, 'test_test')
 
         assert provider.results['summary']['duration'] == 5.0
         assert provider.results['summary']['num_tests'] == 1
@@ -537,6 +537,7 @@
         mock_set_instance_ip.return_value = None
         self.kwargs['running_instance_id'] = 'fakeinstance'
         self.kwargs['test_files'] = ['test_update']
+        self.kwargs['cleanup'] = True
 
         provider = IpaProvider(*args, **self.kwargs)
         provider.ssh_private_key_file = 'tests/data/ida_test'
@@ -545,6 +546,7 @@
         status, results = provider.test_image()
         assert status == 0
         assert mock_distro_update.call_count == 1
+        self.kwargs['cleanup'] = None
 
     @patch.object(IpaProvider, '_set_instance_ip')
     @patch.object(IpaProvider, '_set_image_id')
@@ -589,3 +591,33 @@
         provider = IpaProvider(*args, **self.kwargs)
         provider._wait_on_instance('Stopped')
         assert mock_get_instance_state.call_count == 1
+
+    @patch.object(IpaProvider, '_get_ssh_client')
+    def test_collect_vm_info(self, mock_get_ssh_client):
+        """Test collect_vm_info method. """
+        distro = MagicMock()
+        client = MagicMock()
+        distro.get_vm_info.return_value = \
+            'Failed to collect VM info: Does not exist.'
+        mock_get_ssh_client.return_value = client
+
+        provider = IpaProvider(*args, **self.kwargs)
+        provider.distro = distro
+        provider.log_file = 'fake_file.name'
+        provider.logger = MagicMock()
+
+        with patch('builtins.open', create=True) as mock_open:
+            mock_open.return_value = MagicMock(spec=io.IOBase)
+            file_handle = mock_open.return_value.__enter__.return_value
+
+            provider._collect_vm_info()
+
+            file_handle.write.assert_has_calls([
+                call('\n'),
+                call('Failed to collect VM info: Does not exist.')
+            ])
+
+        provider.logger.info.assert_called_once_with(
+            'Collecting basic info about VM'
+        )
+        assert mock_get_ssh_client.call_count == 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python3-ipa-2.4.0/tests/test_ipa_sles_distro.py 
new/python3-ipa-2.5.0/tests/test_ipa_sles_distro.py
--- old/python3-ipa-2.4.0/tests/test_ipa_sles_distro.py 2018-12-07 
01:07:28.000000000 +0100
+++ new/python3-ipa-2.5.0/tests/test_ipa_sles_distro.py 2018-12-12 
02:51:14.000000000 +0100
@@ -29,22 +29,6 @@
 from unittest.mock import MagicMock, patch
 
 
-def test_sles_set_init_system_exception():
-    """Test SLES set init system method exception."""
-    client = MagicMock()
-    sles = SLES()
-
-    with patch('ipa.ipa_utils.execute_ssh_command', MagicMock(
-               side_effect=Exception('ERROR!'))) as mocked:
-        pytest.raises(
-            IpaSLESException,
-            sles._set_init_system,
-            client
-        )
-
-    mocked.assert_called_once_with(client, 'ps -p 1 -o comm=')
-
-
 def test_sles_get_stop_ssh_cmd():
     """Test SLES get stop ssh cmd method."""
     sles = SLES()


Reply via email to