Beispiel #1
0
class WaitActionTestCase(unittest.TestCase):
    def setUp(self):
        self.utils = AmuletUtils()

    @patch.object(amulet.actions, "get_action_output")
    def test_returns_true_if_completed(self, get_action_output):
        """JSON output is parsed and returns True if the action completed."""

        get_action_output.return_value = {"status": "completed"}

        self.assertTrue(self.utils.wait_on_action("action-id"))
        get_action_output.assert_called_with("action-id", full_output=True)

    @patch.object(amulet.actions, "get_action_output")
    def test_returns_false_if_still_running(self, get_action_output):
        """
        JSON output is parsed and returns False if the action is still running.
        """
        get_action_output.return_value = {"status": "running"}

        self.assertFalse(self.utils.wait_on_action("action-id"))
        get_action_output.assert_called_with("action-id", full_output=True)

    @patch.object(amulet.actions, "get_action_output")
    def test_returns_false_if_no_status(self, get_action_output):
        """
        JSON output is parsed and returns False if there is no action status.
        """
        get_action_output.return_value = {}

        self.assertFalse(self.utils.wait_on_action("action-id"))
        get_action_output.assert_called_with("action-id", full_output=True)
Beispiel #2
0
def ubuntu_basic_deployment(series):
    """ Common test routines to run per-series. """

    # Initialize
    seconds = 900
    u = AmuletUtils(logging.DEBUG)
    d = amulet.Deployment(series=series)
    d.add('ubuntu')

    # Deploy services, wait for started state.  Fail or skip on timeout.
    try:
        d.setup(timeout=seconds)
        sentry_unit = d.sentry.unit['ubuntu/0']
    except amulet.helpers.TimeoutError:
        message = 'Deployment timed out ({}s)'.format(seconds)
        amulet.raise_status(amulet.FAIL, msg=message)
    except:
        raise

    # Confirm Ubuntu release name from the unit.
    release, ret = u.get_ubuntu_release_from_sentry(sentry_unit)
    if ret:
        # Something went wrong trying to query the unit, or it is an
        # unknown/alien release name based on distro-info validation.
        amulet.raise_status(amulet.FAIL, msg=ret)

    if release == series:
        u.log.info('Release/series check:  OK')
    else:
        msg = 'Release/series check:  FAIL ({} != {})'.format(release, series)
        u.log.error(msg)
        amulet.raise_status(amulet.FAIL, msg=msg)
Beispiel #3
0
class StatusGetTestCase(unittest.TestCase):
    def setUp(self):
        self.utils = AmuletUtils()
        self.sentry_unit = FakeSentry()

    def test_status_get(self):
        """
        We can get the status of a unit.
        """
        self.sentry_unit.commands[
            "status-get --format=json --include-data"] = (
                """{"status": "active", "message": "foo"}""", 0)
        self.assertEqual(self.utils.status_get(self.sentry_unit),
                         (u"active", u"foo"))

    def test_status_get_missing_command(self):
        """
        Older releases of Juju have no status-get command.  In those
        cases we should return the "unknown" status.
        """
        self.sentry_unit.commands[
            "status-get --format=json --include-data"] = (
                "status-get: command not found", 127)
        self.assertEqual(self.utils.status_get(self.sentry_unit),
                         (u"unknown", u""))
Beispiel #4
0
class GetUnitProcessIdsTestCase(unittest.TestCase):
    def setUp(self):
        self.utils = AmuletUtils()
        self.sentry_unit = FakeSentry()

    def test_returns_map(self):
        """
        Normal execution returns a dictionary mapping process names to
        PIDs for each unit.
        """
        second_sentry = FakeSentry(name="bar")
        self.sentry_unit.commands['pidof -x "foo"'] = ("123 124", 0)
        second_sentry.commands['pidof -x "bar"'] = ("456 457", 0)

        result = self.utils.get_unit_process_ids({
            self.sentry_unit: ["foo"],
            second_sentry: ["bar"]
        })
        self.assertEqual(
            {
                self.sentry_unit: {
                    "foo": ["123", "124"]
                },
                second_sentry: {
                    "bar": ["456", "457"]
                }
            }, result)

    def test_expect_failure(self):
        """
        Expected failures return empty lists.
        """
        second_sentry = FakeSentry(name="bar")
        self.sentry_unit.commands['pidof -x "foo" || exit 0 && exit 1'] = ("",
                                                                           0)
        second_sentry.commands['pidof -x "bar" || exit 0 && exit 1'] = ("", 0)

        result = self.utils.get_unit_process_ids(
            {
                self.sentry_unit: ["foo"],
                second_sentry: ["bar"]
            },
            expect_success=False)
        self.assertEqual(
            {
                self.sentry_unit: {
                    "foo": []
                },
                second_sentry: {
                    "bar": []
                }
            }, result)
Beispiel #5
0
class GetProcessIdListTestCase(unittest.TestCase):
    def setUp(self):
        self.utils = AmuletUtils()
        self.sentry_unit = FakeSentry()

    def test_returns_pids(self):
        """
        Normal execution returns a list of pids
        """
        self.sentry_unit.commands['pidof -x "foo"'] = ("123 124 125", 0)
        result = self.utils.get_process_id_list(self.sentry_unit, "foo")
        self.assertEqual(["123", "124", "125"], result)

    def test_fails_if_no_process_found(self):
        """
        By default, the expectation is that a process is running. Failure
        to find a given process results in an amulet.FAIL being
        raised.
        """
        self.sentry_unit.commands['pidof -x "foo"'] = ("", 1)
        with self.assertRaises(SystemExit) as cm, captured_output() as (out,
                                                                        err):
            self.utils.get_process_id_list(self.sentry_unit, "foo")
        the_exception = cm.exception
        self.assertEqual(1, the_exception.code)
        self.assertEqual('foo `pidof -x "foo"` returned 1',
                         out.getvalue().rstrip())

    def test_looks_for_scripts(self):
        """
        pidof command uses -x to return a list of pids of scripts
        """
        self.sentry_unit.commands["pidof foo"] = ("", 1)
        self.sentry_unit.commands['pidof -x "foo"'] = ("123 124 125", 0)
        result = self.utils.get_process_id_list(self.sentry_unit, "foo")
        self.assertEqual(["123", "124", "125"], result)

    def test_expect_no_pid(self):
        """
        By setting expectation that there are no pids running the logic
        about when to fail is reversed.
        """
        self.sentry_unit.commands['pidof -x "foo" || exit 0 && exit 1'] = ("",
                                                                           0)
        self.sentry_unit.commands['pidof -x "bar" || exit 0 && exit 1'] = ("",
                                                                           1)
        result = self.utils.get_process_id_list(self.sentry_unit,
                                                "foo",
                                                expect_success=False)
        self.assertEqual([], result)
        with self.assertRaises(SystemExit) as cm, captured_output() as (out,
                                                                        err):
            self.utils.get_process_id_list(self.sentry_unit,
                                           "bar",
                                           expect_success=False)
        the_exception = cm.exception
        self.assertEqual(1, the_exception.code)
        self.assertEqual('foo `pidof -x "bar" || exit 0 && exit 1` returned 1',
                         out.getvalue().rstrip())
Beispiel #6
0
class RunActionTestCase(unittest.TestCase):
    def setUp(self):
        self.utils = AmuletUtils()
        self.sentry_unit = FakeSentry()

    def test_returns_action_id(self):
        """Returns action_id."""

        self.assertEqual("action-id",
                         self.utils.run_action(self.sentry_unit, "foo"))
Beispiel #7
0
class GetProcessIdListTestCase(unittest.TestCase):
    def setUp(self):
        self.utils = AmuletUtils()
        self.sentry_unit = FakeSentry()

    def test_returns_pids(self):
        """
        Normal execution returns a list of pids
        """
        self.sentry_unit.commands['pidof -x "foo"'] = ("123 124 125", 0)
        result = self.utils.get_process_id_list(self.sentry_unit, "foo")
        self.assertEqual(["123", "124", "125"], result)

    @patch("amulet.FAIL", new="failed")
    @patch("amulet.raise_status")
    def test_fails_if_no_process_found(self, mock_raise_status):
        """
        By default, the expectation is that a process is running. Failure
        to find a given process results in an amulet.FAIL being
        raised.
        """
        self.sentry_unit.commands['pidof -x "foo"'] = ("", 1)
        self.utils.get_process_id_list(self.sentry_unit, "foo")
        mock_raise_status.assert_called_once_with(
            "failed", msg='foo `pidof -x "foo"` returned 1 ')

    def test_looks_for_scripts(self):
        """
        pidof command uses -x to return a list of pids of scripts
        """
        self.sentry_unit.commands["pidof foo"] = ("", 1)
        self.sentry_unit.commands['pidof -x "foo"'] = ("123 124 125", 0)
        result = self.utils.get_process_id_list(self.sentry_unit, "foo")
        self.assertEqual(["123", "124", "125"], result)

    @patch("amulet.FAIL", new="failed")
    @patch("amulet.raise_status")
    def test_expect_no_pid(self, mock_raise_status):
        """
        By setting expectation that there are no pids running the logic
        about when to fail is reversed.
        """
        self.sentry_unit.commands['pidof -x "foo" || exit 0 && exit 1'] = ("",
                                                                           0)
        self.sentry_unit.commands['pidof -x "bar" || exit 0 && exit 1'] = ("",
                                                                           1)
        result = self.utils.get_process_id_list(self.sentry_unit,
                                                "foo",
                                                expect_success=False)
        self.assertEqual([], result)
        self.utils.get_process_id_list(self.sentry_unit,
                                       "bar",
                                       expect_success=False)
        mock_raise_status.assert_called_once_with(
            "failed",
            msg='foo `pidof -x "bar" || exit 0 && exit 1` returned 1 ')
Beispiel #8
0
class ValidateServicesByProcessIDTestCase(unittest.TestCase):
    def setUp(self):
        self.utils = AmuletUtils()
        self.sentry_unit = FakeSentry()

    def test_accepts_list_wrong(self):
        """
        Validates that it can accept a list
        """
        expected = {self.sentry_unit: {"foo": [3, 4]}}
        actual = {self.sentry_unit: {"foo": [12345, 67890]}}
        result = self.utils.validate_unit_process_ids(expected, actual)
        self.assertIsNotNone(result)

    def test_accepts_list(self):
        """
        Validates that it can accept a list
        """
        expected = {self.sentry_unit: {"foo": [2, 3]}}
        actual = {self.sentry_unit: {"foo": [12345, 67890]}}
        result = self.utils.validate_unit_process_ids(expected, actual)
        self.assertIsNone(result)

    def test_accepts_string(self):
        """
        Validates that it can accept a string
        """
        expected = {self.sentry_unit: {"foo": 2}}
        actual = {self.sentry_unit: {"foo": [12345, 67890]}}
        result = self.utils.validate_unit_process_ids(expected, actual)
        self.assertIsNone(result)

    def test_accepts_string_wrong(self):
        """
        Validates that it can accept a string
        """
        expected = {self.sentry_unit: {"foo": 3}}
        actual = {self.sentry_unit: {"foo": [12345, 67890]}}
        result = self.utils.validate_unit_process_ids(expected, actual)
        self.assertIsNotNone(result)

    def test_accepts_bool(self):
        """
        Validates that it can accept a boolean
        """
        expected = {self.sentry_unit: {"foo": True}}
        actual = {self.sentry_unit: {"foo": [12345, 67890]}}
        result = self.utils.validate_unit_process_ids(expected, actual)
        self.assertIsNone(result)

    def test_accepts_bool_wrong(self):
        """
        Validates that it can accept a boolean
        """
        expected = {self.sentry_unit: {"foo": True}}
        actual = {self.sentry_unit: {"foo": []}}
        result = self.utils.validate_unit_process_ids(expected, actual)
        self.assertIsNotNone(result)
class BasicDeployment(OpenStackAmuletDeployment):

    utils = AmuletUtils()

    def __init__(self, vip=None, units=1, series="trusty", openstack=None,
                 source=None, stable=False):
        super(BasicDeployment, self).__init__(series, openstack, source,
                                              stable)
        self.units = units
        self.master_unit = None
        self.vip = None
        if units > 1:
            if vip:
                self.vip = vip
            elif 'AMULET_OS_VIP' in os.environ:
                self.vip = os.environ.get('AMULET_OS_VIP')
            elif os.path.isfile('local.yaml'):
                with open('local.yaml', 'rb') as f:
                    self.cfg = yaml.safe_load(f.read())

                self.vip = self.cfg.get('vip')
            else:
                amulet.raise_status(amulet.SKIP,
                                    ("Please set the vip in local.yaml or "
                                     "env var AMULET_OS_VIP to run this test "
                                     "suite"))
        self.log = self.utils.get_logger()

    def _add_services(self):
        """Add services

           Add the services that we're testing, where percona-cluster is local,
           and the rest of the service are from lp branches that are
           compatible with the local charm (e.g. stable or next).
           """
        this_service = {'name': 'percona-cluster',
                        'units': self.units}
        other_services = []
        if self.units > 1:
            other_services.append({'name': 'hacluster'})

        super(BasicDeployment, self)._add_services(this_service,
                                                   other_services)

    def _add_relations(self):
        """Add all of the relations for the services."""
        if self.units > 1:
            relations = {'percona-cluster:ha': 'hacluster:ha'}
            super(BasicDeployment, self)._add_relations(relations)

    def _get_configs(self):
        """Configure all of the services."""
        cfg_percona = {'min-cluster-size': self.units,
                       'vip': self.vip}

        cfg_ha = {'debug': True,
                  'corosync_key': ('xZP7GDWV0e8Qs0GxWThXirNNYlScgi3sRTdZk/IXKD'
                                   'qkNFcwdCWfRQnqrHU/6mb6sz6OIoZzX2MtfMQIDcXu'
                                   'PqQyvKuv7YbRyGHmQwAWDUA4ed759VWAO39kHkfWp9'
                                   'y5RRk/wcHakTcWYMwm70upDGJEP00YT3xem3NQy27A'
                                   'C1w=')}

        configs = {}
        if self.units > 1:
            cfg_ha['cluster_count'] = str(self.units)
            configs['hacluster'] = cfg_ha
        configs['percona-cluster'] = cfg_percona

        return configs

    def _configure_services(self):
        super(BasicDeployment, self)._configure_services(self._get_configs())

    def run(self):
        self._add_services()
        self._add_relations()
        self._configure_services()
        self._deploy()
        self.d.sentry.wait()
        self.test_deployment()

    def test_deployment(self):
        '''Top level test function executor'''
        self.test_pacemaker()
        self.test_pxc_running()
        self.test_bootstrapped_and_clustered()
        self.test_bootstrap_uuid_set_in_the_relation()
        self.test_pause_resume()
        self.test_kill_master()

    def test_pacemaker(self):
        '''
        Ensure that pacemaker and corosync are correctly configured in
        clustered deployments.

        side effect: self.master_unit should be set after execution
        '''
        if self.units > 1:
            i = 0
            while i < 30 and not self.master_unit:
                self.master_unit = self.find_master()
                i += 1
                time.sleep(10)

            msg = 'percona-cluster vip not found'
            assert self.master_unit is not None, msg

            _, code = self.master_unit.run('sudo crm_verify --live-check')
            assert code == 0, "'crm_verify --live-check' failed"

            resources = ['res_mysql_vip']
            resources += ['res_mysql_monitor:%d' %
                          m for m in range(self.units)]

            assert sorted(self.get_pcmkr_resources()) == sorted(resources)
        else:
            self.master_unit = self.find_master(ha=False)

    def test_pxc_running(self):
        '''
        Ensure PXC is running on all units
        '''
        for unit in self.d.sentry['percona-cluster']:
            assert self.is_mysqld_running(unit), 'mysql not running: %s' % unit

    def test_bootstrapped_and_clustered(self):
        '''
        Ensure PXC is bootstrapped and that peer units are clustered
        '''
        self.log.info('Ensuring PXC is bootstrapped')
        msg = "Percona cluster failed to bootstrap"
        assert self.is_pxc_bootstrapped(), msg

        self.log.info('Checking PXC cluster size == {}'.format(self.units))
        got = int(self.get_cluster_size())
        msg = ("Percona cluster unexpected size"
               " (wanted=%s, got=%s)" % (self.units, got))
        assert got == self.units, msg

    def test_bootstrap_uuid_set_in_the_relation(self):
        """Verify that the bootstrap-uuid attribute was set by the leader and
        all the peers where notified.
        """
        (leader_uuid, code) = self.master_unit.run("leader-get bootstrap-uuid")
        assert leader_uuid

        cmd_rel_get = ("relation-get -r `relation-ids cluster` "
                       "bootstrap-uuid %s")
        units = self.d.sentry['percona-cluster']
        for unit in units:
            for peer in units:
                cmd = cmd_rel_get % peer.info['unit_name']
                self.log.debug(cmd)
                (output, code) = unit.run(cmd)
                assert code == 0
                assert output == leader_uuid, "%s != %s" % (output,
                                                            leader_uuid)

    def test_pause_resume(self):
        '''
        Ensure pasue/resume actions stop/start mysqld on units
        '''
        self.log.info('Testing pause/resume actions')
        self.log.info('Pausing service on first PXC unit')
        unit = self.d.sentry['percona-cluster'][0]
        assert self.is_mysqld_running(unit), 'mysql not running'
        assert self.utils.status_get(unit)[0] == "active"

        action_id = self.utils.run_action(unit, "pause")
        assert self.utils.wait_on_action(action_id), "Pause action failed."

        # Note that is_mysqld_running will print an error message when
        # mysqld is not running.  This is by design but it looks odd
        # in the output.
        assert not self.is_mysqld_running(unit=unit), \
            "mysqld is still running!"

        self.log.info('Resuming service on first PXC unit')
        assert self.utils.status_get(unit)[0] == "maintenance"
        action_id = self.utils.run_action(unit, "resume")
        assert self.utils.wait_on_action(action_id), "Resume action failed"
        assert self.utils.status_get(unit)[0] == "active"
        assert self.is_mysqld_running(unit=unit), \
            "mysqld not running after resume."

    def test_kill_master(self):
        '''
        Ensure that killing the mysqld on the master unit results
        in a VIP failover
        '''
        self.log.info('Testing failover of master unit on mysqld failure')
        # we are going to kill the master
        old_master = self.master_unit
        self.log.info(
            'kill -9 mysqld on {}'.format(self.master_unit.info['unit_name'])
        )
        self.master_unit.run('sudo killall -9 mysqld')

        self.log.info('looking for the new master')
        i = 0
        changed = False
        while i < 10 and not changed:
            i += 1
            time.sleep(5)  # give some time to pacemaker to react
            new_master = self.find_master()

            if (new_master and new_master.info['unit_name'] !=
                    old_master.info['unit_name']):
                self.log.info(
                    'New master unit detected'
                    ' on {}'.format(new_master.info['unit_name'])
                )
                changed = True

        assert changed, "The master didn't change"

        assert self.is_port_open(address=self.vip), 'cannot connect to vip'

    def find_master(self, ha=True):
        for unit in self.d.sentry['percona-cluster']:
            if not ha:
                return unit

            # is the vip running here?
            output, code = unit.run('sudo ip a | grep "inet %s/"' % self.vip)
            self.log.info("Checking {}".format(unit.info['unit_name']))
            self.log.debug(output)
            if code == 0:
                self.log.info('vip ({}) running in {}'.format(
                    self.vip,
                    unit.info['unit_name'])
                )
                return unit

    def get_pcmkr_resources(self, unit=None):
        if unit:
            u = unit
        else:
            u = self.master_unit

        output, code = u.run('sudo crm_resource -l')

        assert code == 0, 'could not get "crm resource list"'

        return output.split('\n')

    def is_mysqld_running(self, unit=None):
        if unit:
            u = unit
        else:
            u = self.master_unit

        _, code = u.run('pidof mysqld')
        if code != 0:
            self.log.debug("command returned non-zero '%s'" % (code))
            return False

        return True

    def get_wsrep_value(self, attr, unit=None):
        if unit:
            u = unit
        else:
            u = self.master_unit
        root_password, _ = u.run('leader-get root-password')
        cmd = ("mysql -uroot -p{} -e\"show status like '{}';\"| "
               "grep {}".format(root_password, attr, attr))
        output, code = u.run(cmd)
        if code != 0:
            self.log.debug("command returned non-zero '%s'" % (code))
            return ""

        value = re.search(r"^.+?\s+(.+)", output).group(1)
        self.log.info("%s = %s" % (attr, value))
        return value

    def is_pxc_bootstrapped(self, unit=None):
        value = self.get_wsrep_value('wsrep_ready', unit)
        return value.lower() in ['on', 'ready']

    def get_cluster_size(self, unit=None):
        return self.get_wsrep_value('wsrep_cluster_size', unit)

    def is_port_open(self, unit=None, port='3306', address=None):
        if unit:
            addr = unit.info['public-address']
        elif address:
            addr = address
        else:
            raise Exception('Please provide a unit or address')

        try:
            telnetlib.Telnet(addr, port)
            return True
        except socket.error as e:
            if e.errno == 113:
                self.log.error("could not connect to %s:%s" % (addr, port))
            if e.errno == 111:
                self.log.error("connection refused connecting"
                               " to %s:%s" % (addr,
                                              port))
            return False
#!/usr/bin/python3
# test percona-cluster pause and resum

import basic_deployment
from charmhelpers.contrib.amulet.utils import AmuletUtils

utils = AmuletUtils()


class PauseResume(basic_deployment.BasicDeployment):
    def run(self):
        super(PauseResume, self).run()
        uid = 'percona-cluster/0'
        unit = self.d.sentry.unit[uid]
        assert self.is_mysqld_running(unit), 'mysql not running: %s' % uid
        assert utils.status_get(unit)[0] == "active"

        action_id = utils.run_action(unit, "pause")
        assert utils.wait_on_action(action_id), "Pause action failed."

        # Note that is_mysqld_running will print an error message when
        # mysqld is not running.  This is by design but it looks odd
        # in the output.
        assert not self.is_mysqld_running(unit=unit), \
            "mysqld is still running!"

        assert utils.status_get(unit)[0] == "maintenance"
        action_id = utils.run_action(unit, "resume")
        assert utils.wait_on_action(action_id), "Resume action failed"
        assert utils.status_get(unit)[0] == "active"
        assert self.is_mysqld_running(unit=unit), \
Beispiel #11
0
 def setUp(self):
     self.utils = AmuletUtils()
     self.sentry_unit = FakeSentry()
Beispiel #12
0
class ValidateServicesByNameTestCase(unittest.TestCase):
    def setUp(self):
        self.utils = AmuletUtils()
        self.sentry_unit = FakeSentry()

    def test_errors_for_unknown_upstart_service(self):
        """
        Returns a message if the Upstart service is unknown.
        """
        self.sentry_unit.commands["lsb_release -cs"] = "trusty", 0
        self.sentry_unit.commands["sudo status foo"] = (
            "status: Unknown job: foo", 1)

        result = self.utils.validate_services_by_name(
            {self.sentry_unit: ["foo"]})
        self.assertIsNotNone(result)

    def test_none_for_started_upstart_service(self):
        """
        Returns None if the Upstart service is running.
        """
        self.sentry_unit.commands["lsb_release -cs"] = "trusty", 0
        self.sentry_unit.commands["sudo status foo"] = (
            "foo start/running, process 42", 0)

        result = self.utils.validate_services_by_name(
            {self.sentry_unit: ["foo"]})
        self.assertIsNone(result)

    def test_errors_for_stopped_upstart_service(self):
        """
        Returns a message if the Upstart service is stopped.
        """
        self.sentry_unit.commands["lsb_release -cs"] = "trusty", 0
        self.sentry_unit.commands["sudo status foo"] = "foo stop/waiting", 0

        result = self.utils.validate_services_by_name(
            {self.sentry_unit: ["foo"]})
        self.assertIsNotNone(result)

    def test_errors_for_unknown_systemd_service(self):
        """
        Returns a message if a systemd service is unknown.
        """
        self.sentry_unit.commands["lsb_release -cs"] = "vivid", 0
        self.sentry_unit.commands["sudo service foo status"] = (u"""\
\u25cf foo.service
   Loaded: not-found (Reason: No such file or directory)
   Active: inactive (dead)
""", 3)

        result = self.utils.validate_services_by_name(
            {self.sentry_unit: ["foo"]})
        self.assertIsNotNone(result)

    def test_none_for_started_systemd_service(self):
        """
        Returns None if a systemd service is running.
        """
        self.sentry_unit.commands["lsb_release -cs"] = "vivid", 0
        self.sentry_unit.commands["sudo service foo status"] = (u"""\
\u25cf foo.service - Foo
   Loaded: loaded (/lib/systemd/system/foo.service; enabled)
   Active: active (exited) since Thu 1970-01-01 00:00:00 UTC; 42h 42min ago
 Main PID: 3 (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/foo.service
""", 0)
        result = self.utils.validate_services_by_name(
            {self.sentry_unit: ["foo"]})
        self.assertIsNone(result)

    def test_errors_for_stopped_systemd_service(self):
        """
        Returns a message if a systemd service is stopped.
        """
        self.sentry_unit.commands["lsb_release -cs"] = "vivid", 0
        self.sentry_unit.commands["sudo service foo status"] = (u"""\
\u25cf foo.service - Foo
   Loaded: loaded (/lib/systemd/system/foo.service; disabled)
   Active: inactive (dead)
""", 3)
        result = self.utils.validate_services_by_name(
            {self.sentry_unit: ["foo"]})
        self.assertIsNotNone(result)
Beispiel #13
0
 def setUp(self):
     self.utils = AmuletUtils()