Пример #1
0
    def test_cache_device(self):
        """Test replacing a disk in use."""
        logging.info('Running add-disk action with a caching device')
        mon = next(iter(zaza_model.get_units('ceph-mon'))).entity_id
        osds = [x.entity_id for x in zaza_model.get_units('ceph-osd')]
        params = []
        for unit in osds:
            loop_dev = self.loop_devs[unit]
            params.append({'unit': unit, 'device': loop_dev})
            action_obj = zaza_model.run_action(unit_name=unit,
                                               action_name='add-disk',
                                               action_params={
                                                   'osd-devices': loop_dev,
                                                   'partition-size': 5
                                               })
            zaza_utils.assertActionRanOK(action_obj)
        zaza_model.wait_for_application_states()

        logging.info('Removing previously added disks')
        for param in params:
            osd_id = self.get_local_osd_id(param['unit'])
            param.update({'osd-id': osd_id})
            action_obj = zaza_model.run_action(unit_name=param['unit'],
                                               action_name='remove-disk',
                                               action_params={
                                                   'osd-ids': osd_id,
                                                   'timeout': 5,
                                                   'format': 'json',
                                                   'purge': False
                                               })
            zaza_utils.assertActionRanOK(action_obj)
            results = json.loads(action_obj.data['results']['message'])
            results = results[next(iter(results))]
            self.assertEqual(results['osd-ids'], osd_id)
            zaza_model.run_on_unit(param['unit'], 'partprobe')
        zaza_model.wait_for_application_states()

        logging.info('Recycling previously removed OSDs')
        for param in params:
            action_obj = zaza_model.run_action(unit_name=param['unit'],
                                               action_name='add-disk',
                                               action_params={
                                                   'osd-devices':
                                                   param['device'],
                                                   'osd-ids': param['osd-id'],
                                                   'partition-size': 4
                                               })
            zaza_utils.assertActionRanOK(action_obj)
        zaza_model.wait_for_application_states()
        self.assertEqual(len(osds) * 2, self.get_num_osds(mon))

        # Finally, remove all the added OSDs that are backed by loop devices.
        for param in params:
            osd_id = self.get_local_osd_id(param['unit'])
            zaza_model.run_action(unit_name=param['unit'],
                                  action_name='remove-disk',
                                  action_params={
                                      'osd-ids': osd_id,
                                      'purge': True
                                  })
Пример #2
0
    def osd_out_in(self, services):
        """Run OSD out and OSD in tests.

        Remove OSDs and then add them back in on a unit checking that services
        are in the required state after each action

        :param services: Services expected to be restarted when config_file is
                         changed.
        :type services: list
        """
        zaza_model.block_until_service_status(self.lead_unit,
                                              services,
                                              'running',
                                              model_name=self.model_name)
        zaza_model.block_until_unit_wl_status(self.lead_unit,
                                              'active',
                                              model_name=self.model_name)
        zaza_model.run_action(self.lead_unit,
                              'osd-out',
                              model_name=self.model_name)
        zaza_model.block_until_unit_wl_status(self.lead_unit,
                                              'maintenance',
                                              model_name=self.model_name)
        zaza_model.block_until_all_units_idle(model_name=self.model_name)
        zaza_model.run_action(self.lead_unit,
                              'osd-in',
                              model_name=self.model_name)
        zaza_model.block_until_unit_wl_status(self.lead_unit,
                                              'active',
                                              model_name=self.model_name)
        zaza_model.block_until_all_units_idle(model_name=self.model_name)
        zaza_model.block_until_service_status(self.lead_unit,
                                              services,
                                              'running',
                                              model_name=self.model_name)
Пример #3
0
 def test_run_action(self):
     self.patch_object(model, 'Model')
     self.patch_object(model, 'get_unit_from_name')
     self.get_unit_from_name.return_value = self.unit1
     self.Model.return_value = self.Model_mock
     model.run_action('app/2', 'modelname', 'backup',
                      {'backup_dir': '/dev/null'})
     self.unit1.run_action.assert_called_once_with(
         'backup',
         backup_dir='/dev/null')
Пример #4
0
    def pause_resume(self, services, pgrep_full=False):
        """Run Pause and resume tests.

        Pause and then resume a unit checking that services are in the
        required state after each action

        :param services: Services expected to be restarted when config_file is
                         changed.
        :type services: list
        :param pgrep_full: Should pgrep be used rather than pidof to identify
                           a service.
        :type  pgrep_full: bool
        """
        model.block_until_service_status(
            self.lead_unit,
            services,
            'running',
            model_name=self.model_name,
            pgrep_full=pgrep_full)
        model.block_until_unit_wl_status(
            self.lead_unit,
            'active',
            model_name=self.model_name)
        model.run_action(
            self.lead_unit,
            'pause',
            model_name=self.model_name)
        model.block_until_unit_wl_status(
            self.lead_unit,
            'maintenance',
            model_name=self.model_name)
        model.block_until_all_units_idle(model_name=self.model_name)
        model.block_until_service_status(
            self.lead_unit,
            services,
            'stopped',
            model_name=self.model_name,
            pgrep_full=pgrep_full)
        yield
        model.run_action(
            self.lead_unit,
            'resume',
            model_name=self.model_name)
        model.block_until_unit_wl_status(
            self.lead_unit,
            'active',
            model_name=self.model_name)
        model.block_until_all_units_idle(model_name=self.model_name)
        model.block_until_service_status(
            self.lead_unit,
            services,
            'running',
            model_name=self.model_name,
            pgrep_full=pgrep_full)
Пример #5
0
    def clear_hooks(self):
        """Clear and deferred hooks.

        Run any deferred hooks.
        """
        # Use action to run any deferred restarts
        for unit in model.get_units(self.application_name):
            logging.info("Running run-deferred-hooks on {}".format(
                unit.entity_id))
            model.run_action(
                unit.entity_id,
                'run-deferred-hooks',
                raise_on_failure=True)
Пример #6
0
 def test_ghost_nfs_share(self):
     """Ensure ghost-share action bind mounts NFS share."""
     generic_utils.assertActionRanOK(
         zaza_model.run_action(
             self.lead_unit,
             'ghost-share',
             action_params={'nfs-shares': '10.20.0.1:/srv/testing'},
             model_name=self.model_name))
Пример #7
0
    def check_clear_restarts(self):
        """Clear and deferred restarts and check status.

        Clear and deferred restarts and then check the workload status message
        for each unit.
        """
        # Use action to run any deferred restarts
        for unit in model.get_units(self.application_name):
            logging.info("Running restart-services on {}".format(
                unit.entity_id))
            model.run_action(
                unit.entity_id,
                'restart-services',
                action_params={'deferred-only': True},
                raise_on_failure=True)

        # Check workload status no longer shows deferred restarts.
        self.check_status_message_is_clear()
Пример #8
0
    def test_blacklist(self):
        """Check the blacklist action.

        The blacklist actions execute and behave as expected.
        """
        logging.info('Checking blacklist-add-disk and'
                     'blacklist-remove-disk actions...')
        unit_name = 'ceph-osd/0'

        zaza_model.block_until_unit_wl_status(unit_name, 'active')

        # Attempt to add device with non-absolute path should fail
        action_obj = zaza_model.run_action(
            unit_name=unit_name,
            action_name='blacklist-add-disk',
            action_params={'osd-devices': 'vda'})
        self.assertTrue(action_obj.status != 'completed')
        zaza_model.block_until_unit_wl_status(unit_name, 'active')

        # Attempt to add device with non-existent path should fail
        action_obj = zaza_model.run_action(
            unit_name=unit_name,
            action_name='blacklist-add-disk',
            action_params={'osd-devices': '/non-existent'})
        self.assertTrue(action_obj.status != 'completed')
        zaza_model.block_until_unit_wl_status(unit_name, 'active')

        # Attempt to add device with existent path should succeed
        action_obj = zaza_model.run_action(
            unit_name=unit_name,
            action_name='blacklist-add-disk',
            action_params={'osd-devices': '/dev/vda'})
        self.assertEqual('completed', action_obj.status)
        zaza_model.block_until_unit_wl_status(unit_name, 'active')

        # Attempt to remove listed device should always succeed
        action_obj = zaza_model.run_action(
            unit_name=unit_name,
            action_name='blacklist-remove-disk',
            action_params={'osd-devices': '/dev/vda'})
        self.assertEqual('completed', action_obj.status)
        zaza_model.block_until_unit_wl_status(unit_name, 'active')
        logging.debug('OK')
Пример #9
0
    def test_501_security_checklist_action(self):
        """Verify expected result on a default install.

        Ported from amulet tests.
        """
        logging.info("Testing security-checklist")
        unit_name = zaza_model.get_lead_unit_name('openstack-dashboard')
        action = zaza_model.run_action(unit_name, 'security-checklist')
        assert action.data.get(u"status") == "failed", \
            "Security check is expected to not pass by default"
Пример #10
0
    def run_show_deferred_events_action(self):
        """Run show-deferred-events and return results.

        :returns: Data from action run
        :rtype: Dict
        """
        unit = model.get_units(self.application_name)[0]
        action = model.run_action(
            unit.entity_id,
            'show-deferred-events',
            raise_on_failure=True)
        return yaml.safe_load(action.data['results']['output'])
Пример #11
0
    def test_update_trilio_action(self):
        """Test that the action runs succesfully."""
        action_name = 'update-trilio'
        actions = zaza_model.get_actions(self.application_name)
        if action_name not in actions:
            raise unittest.SkipTest(
                'Action {} not defined'.format(action_name))

        generic_utils.assertActionRanOK(
            zaza_model.run_action(self.lead_unit,
                                  action_name,
                                  action_params={},
                                  model_name=self.model_name))
Пример #12
0
    def pause_resume(self, services):
        """Run Pause and resume tests.

        Override the default implementation since pausing ceph units
        doesn't stop the services.
        Pause and then resume a unit checking that services are in the
        required state after each action

        :param services: Services expected to be restarted when config_file is
                         changed.
        :type services: list
        """
        zaza_model.block_until_service_status(self.lead_unit,
                                              services,
                                              'running',
                                              model_name=self.model_name)
        zaza_model.block_until_unit_wl_status(self.lead_unit,
                                              'active',
                                              model_name=self.model_name)
        zaza_model.run_action(self.lead_unit,
                              'pause',
                              model_name=self.model_name)
        zaza_model.block_until_unit_wl_status(self.lead_unit,
                                              'maintenance',
                                              model_name=self.model_name)
        zaza_model.block_until_all_units_idle(model_name=self.model_name)
        zaza_model.run_action(self.lead_unit,
                              'resume',
                              model_name=self.model_name)
        zaza_model.block_until_unit_wl_status(self.lead_unit,
                                              'active',
                                              model_name=self.model_name)
        zaza_model.block_until_all_units_idle(model_name=self.model_name)
        zaza_model.block_until_service_status(self.lead_unit,
                                              services,
                                              'running',
                                              model_name=self.model_name)
Пример #13
0
    def pause_resume(self, services):
        """Run Pause and resume tests.

        Pause and then resume a unit checking that services are in the
        required state after each action

        :param services: Services expected to be restarted when config_file is
                         changed.
        :type services: list
        """
        model.block_until_service_status(self.lead_unit,
                                         services,
                                         'running',
                                         model_name=self.model_name)
        model.block_until_unit_wl_status(self.lead_unit,
                                         'active',
                                         model_name=self.model_name)
        model.run_action(self.lead_unit, 'pause', model_name=self.model_name)
        model.block_until_unit_wl_status(self.lead_unit,
                                         'maintenance',
                                         model_name=self.model_name)
        model.block_until_all_units_idle(model_name=self.model_name)
        model.block_until_service_status(self.lead_unit,
                                         services,
                                         'stopped',
                                         model_name=self.model_name)
        yield
        model.run_action(self.lead_unit, 'resume', model_name=self.model_name)
        model.block_until_unit_wl_status(self.lead_unit,
                                         'active',
                                         model_name=self.model_name)
        model.block_until_all_units_idle(model_name=self.model_name)
        model.block_until_service_status(self.lead_unit,
                                         services,
                                         'running',
                                         model_name=self.model_name)
Пример #14
0
    def test_list_disks(self):
        """Test the list-disks action.

        The list-disks action execute.
        """
        logging.info('Checking list-disks action...')
        unit_name = 'ceph-osd/0'

        zaza_model.block_until_unit_wl_status(unit_name, 'active')

        action_obj = zaza_model.run_action(
            unit_name=unit_name,
            action_name='list-disks',
        )
        self.assertEqual('completed', action_obj.status)
        zaza_model.block_until_unit_wl_status(unit_name, 'active')
        logging.debug('OK')
Пример #15
0
def series_upgrade_application(application, pause_non_leader_primary=True,
                               pause_non_leader_subordinate=True,
                               from_series="trusty", to_series="xenial",
                               origin='openstack-origin',
                               completed_machines=[],
                               files=None, workaround_script=None,
                               post_upgrade_functions=None):
    """Series upgrade application.

    Wrap all the functionality to handle series upgrade for a given
    application. Including pausing non-leader units.

    :param application: Name of application to upgrade series
    :type application: str
    :param pause_non_leader_primary: Whether the non-leader applications should
                                     be paused
    :type pause_non_leader_primary: bool
    :param pause_non_leader_subordinate: Whether the non-leader subordinate
                                         hacluster applications should be
                                         paused
    :type pause_non_leader_subordinate: bool
    :param from_series: The series from which to upgrade
    :type from_series: str
    :param to_series: The series to which to upgrade
    :type to_series: str
    :param origin: The configuration setting variable name for changing origin
                   source. (openstack-origin or source)
    :type origin: str
    :param completed_machines: List of completed machines which do no longer
                               require series upgrade.
    :type completed_machines: list
    :param files: Workaround files to scp to unit under upgrade
    :type files: list
    :param workaround_script: Workaround script to run during series upgrade
    :type workaround_script: str
    :returns: None
    :rtype: None
    """
    status = model.get_status().applications[application]

    # For some applications (percona-cluster) the leader unit must upgrade
    # first. For API applications the non-leader haclusters must be paused
    # before upgrade. Finally, for some applications this is arbitrary but
    # generalized.
    leader = None
    non_leaders = []
    for unit in status["units"]:
        if status["units"][unit].get("leader"):
            leader = unit
        else:
            non_leaders.append(unit)

    # Pause the non-leaders
    for unit in non_leaders:
        if pause_non_leader_subordinate:
            if status["units"][unit].get("subordinates"):
                for subordinate in status["units"][unit]["subordinates"]:
                    _app = subordinate.split('/')[0]
                    if _app in SUBORDINATE_PAUSE_RESUME_BLACKLIST:
                        logging.info("Skipping pausing {} - blacklisted"
                                     .format(subordinate))
                    else:
                        logging.info("Pausing {}".format(subordinate))
                        model.run_action(
                            subordinate, "pause", action_params={})
        if pause_non_leader_primary:
            logging.info("Pausing {}".format(unit))
            model.run_action(unit, "pause", action_params={})

    machine = status["units"][leader]["machine"]
    # Series upgrade the leader
    logging.info("Series upgrade leader: {}".format(leader))
    if machine not in completed_machines:
        series_upgrade(leader, machine,
                       from_series=from_series, to_series=to_series,
                       origin=origin, workaround_script=workaround_script,
                       files=files,
                       post_upgrade_functions=post_upgrade_functions)
        completed_machines.append(machine)
    else:
        logging.info("Skipping unit: {}. Machine: {} already upgraded."
                     "But setting origin on the application {}"
                     .format(unit, machine, application))
        logging.info("Set origin on {}".format(application))
        set_origin(application, origin)
        model.block_until_all_units_idle()

    # Series upgrade the non-leaders
    for unit in non_leaders:
        machine = status["units"][unit]["machine"]
        if machine not in completed_machines:
            logging.info("Series upgrade non-leader unit: {}"
                         .format(unit))
            series_upgrade(unit, machine,
                           from_series=from_series, to_series=to_series,
                           origin=origin, workaround_script=workaround_script,
                           files=files,
                           post_upgrade_functions=post_upgrade_functions)
            completed_machines.append(machine)
        else:
            logging.info("Skipping unit: {}. Machine: {} already upgraded. "
                         "But setting origin on the application {}"
                         .format(unit, machine, application))
            logging.info("Set origin on {}".format(application))
            set_origin(application, origin)
            model.block_until_all_units_idle()
Пример #16
0
    def test_blocked_when_non_pristine_disk_appears(self):
        """Test blocked state with non-pristine disk.

        Validate that charm goes into blocked state when it is presented with
        new block devices that have foreign data on them.
        Instances used in UOSCI has a flavour with ephemeral storage in
        addition to the bootable instance storage.  The ephemeral storage
        device is partitioned, formatted and mounted early in the boot process
        by cloud-init.
        As long as the device is mounted the charm will not attempt to use it.
        If we unmount it and trigger the config-changed hook the block device
        will appear as a new and previously untouched device for the charm.
        One of the first steps of device eligibility checks should be to make
        sure we are seeing a pristine and empty device before doing any
        further processing.
        As the ephemeral device will have data on it we can use it to validate
        that these checks work as intended.
        """
        logging.info('Checking behaviour when non-pristine disks appear...')
        logging.info('Configuring ephemeral-unmount...')
        alternate_conf = {
            'ephemeral-unmount': '/mnt',
            'osd-devices': '/dev/vdb'
        }
        juju_service = 'ceph-osd'
        zaza_model.set_application_config(juju_service, alternate_conf)
        ceph_osd_states = {
            'ceph-osd': {
                'workload-status': 'blocked',
                'workload-status-message': 'Non-pristine'
            }
        }
        zaza_model.wait_for_application_states(states=ceph_osd_states)
        logging.info('Units now in blocked state, running zap-disk action...')
        unit_names = ['ceph-osd/0', 'ceph-osd/1', 'ceph-osd/2']
        for unit_name in unit_names:
            zap_disk_params = {
                'devices': '/dev/vdb',
                'i-really-mean-it': True,
            }
            action_obj = zaza_model.run_action(unit_name=unit_name,
                                               action_name='zap-disk',
                                               action_params=zap_disk_params)
            logging.debug('Result of action: {}'.format(action_obj))

        logging.info('Running add-disk action...')
        for unit_name in unit_names:
            add_disk_params = {
                'osd-devices': '/dev/vdb',
            }
            action_obj = zaza_model.run_action(unit_name=unit_name,
                                               action_name='add-disk',
                                               action_params=add_disk_params)
            logging.debug('Result of action: {}'.format(action_obj))

        logging.info('Wait for idle/ready status...')
        zaza_model.wait_for_application_states()

        logging.info('OK')

        set_default = {
            'ephemeral-unmount': '',
            'osd-devices': '/dev/vdb',
        }

        current_release = zaza_openstack.get_os_release()
        bionic_train = zaza_openstack.get_os_release('bionic_train')
        if current_release < bionic_train:
            set_default['osd-devices'] = '/dev/vdb /srv/ceph'

        logging.info('Restoring to default configuration...')
        zaza_model.set_application_config(juju_service, set_default)

        zaza_model.wait_for_application_states()
Пример #17
0
    def test_blocked_when_non_pristine_disk_appears(self):
        """Test blocked state with non-pristine disk.

        Validate that charm goes into blocked state when it is presented with
        new block devices that have foreign data on them.
        Instances used in UOSCI has a flavour with ephemeral storage in
        addition to the bootable instance storage.  The ephemeral storage
        device is partitioned, formatted and mounted early in the boot process
        by cloud-init.
        As long as the device is mounted the charm will not attempt to use it.
        If we unmount it and trigger the config-changed hook the block device
        will appear as a new and previously untouched device for the charm.
        One of the first steps of device eligibility checks should be to make
        sure we are seeing a pristine and empty device before doing any
        further processing.
        As the ephemeral device will have data on it we can use it to validate
        that these checks work as intended.
        """
        current_release = zaza_openstack.get_os_release()
        focal_ussuri = zaza_openstack.get_os_release('focal_ussuri')
        if current_release >= focal_ussuri:
            # NOTE(ajkavanagh) - focal (on ServerStack) is broken for /dev/vdb
            # and so this test can't pass: LP#1842751 discusses the issue, but
            # basically the snapd daemon along with lxcfs results in /dev/vdb
            # being mounted in the lxcfs process namespace.  If the charm
            # 'tries' to umount it, it can (as root), but the mount is still
            # 'held' by lxcfs and thus nothing else can be done with it.  This
            # is only a problem in serverstack with images with a default
            # /dev/vdb ephemeral
            logging.warn("Skipping pristine disk test for focal and higher")
            return
        logging.info('Checking behaviour when non-pristine disks appear...')
        logging.info('Configuring ephemeral-unmount...')
        alternate_conf = {
            'ephemeral-unmount': '/mnt',
            'osd-devices': '/dev/vdb'
        }
        juju_service = 'ceph-osd'
        zaza_model.set_application_config(juju_service, alternate_conf)
        ceph_osd_states = {
            'ceph-osd': {
                'workload-status': 'blocked',
                'workload-status-message': 'Non-pristine'
            }
        }
        zaza_model.wait_for_application_states(states=ceph_osd_states)
        logging.info('Units now in blocked state, running zap-disk action...')
        unit_names = ['ceph-osd/0', 'ceph-osd/1', 'ceph-osd/2']
        for unit_name in unit_names:
            zap_disk_params = {
                'devices': '/dev/vdb',
                'i-really-mean-it': True,
            }
            action_obj = zaza_model.run_action(
                unit_name=unit_name,
                action_name='zap-disk',
                action_params=zap_disk_params
            )
            logging.debug('Result of action: {}'.format(action_obj))

        logging.info('Running add-disk action...')
        for unit_name in unit_names:
            add_disk_params = {
                'osd-devices': '/dev/vdb',
            }
            action_obj = zaza_model.run_action(
                unit_name=unit_name,
                action_name='add-disk',
                action_params=add_disk_params
            )
            logging.debug('Result of action: {}'.format(action_obj))

        logging.info('Wait for idle/ready status...')
        zaza_model.wait_for_application_states()

        logging.info('OK')

        set_default = {
            'ephemeral-unmount': '',
            'osd-devices': '/dev/vdb',
        }

        current_release = zaza_openstack.get_os_release()
        bionic_train = zaza_openstack.get_os_release('bionic_train')
        if current_release < bionic_train:
            set_default['osd-devices'] = '/dev/vdb /srv/ceph'

        logging.info('Restoring to default configuration...')
        zaza_model.set_application_config(juju_service, set_default)

        zaza_model.wait_for_application_states()