Beispiel #1
0
    def _late_setup(self):
        self.logger.info('Checking maintenance mode')
        vmstatus = vm_status.VmStatus()
        status = vmstatus.get_status()
        self.logger.debug('hosted-engine-status: {s}'.format(s=status))
        if not status['global_maintenance']:
            self.logger.error(
                _('Please enable global maintenance mode before '
                  'upgrading or restoring'))
            raise RuntimeError(_('Not in global maintenance mode'))

        if self.environment[ohostedcons.CoreEnv.ROLLBACK_UPGRADE]:
            if status['engine_vm_up']:
                self.logger.error(
                    _('The engine VM seams up, please stop it before '
                      'restoring.'))
                raise RuntimeError(_('Engine VM is up'))
            else:
                self.logger.info(_('The engine VM is down.'))
        if self.environment[ohostedcons.CoreEnv.UPGRADING_APPLIANCE]:
            cli = self.environment[ohostedcons.VDSMEnv.VDS_CLI]
            response = cli.list()
            self.logger.debug(response)
            if response['status']['code'] == 0:
                if 'items' in response:
                    vms = set(response['items'])
                else:
                    vms = set([])
                if self.environment[ohostedcons.VMEnv.VM_UUID] not in vms:
                    raise RuntimeError(
                        _('The engine VM is not running on this host'))
                else:
                    self.logger.info('The engine VM is running on this host')
            else:
                raise RuntimeError(_('Unable to get VM list from VDSM'))
    def _late_setup(self):
        self.logger.info('Checking maintenance mode')
        vmstatus = vm_status.VmStatus()
        status = vmstatus.get_status()
        self.logger.debug('hosted-engine-status: {s}'.format(s=status))
        if not status['global_maintenance']:
            self.logger.error(
                _('Please enable global maintenance mode before '
                  'upgrading or restoring'))
            raise RuntimeError(_('Not in global maintenance mode'))

        if self.environment[ohostedcons.CoreEnv.ROLLBACK_UPGRADE]:
            if status['engine_vm_up']:
                self.logger.error(
                    _('The engine VM seams up, please stop it before '
                      'restoring.'))
                raise RuntimeError(_('Engine VM is up'))
            else:
                self.logger.info(_('The engine VM is down.'))
        if self.environment[ohostedcons.CoreEnv.UPGRADING_APPLIANCE]:
            cli = self.environment[ohostedcons.VDSMEnv.VDS_CLI]
            try:
                vmList = cli.Host.getVMList()
                self.logger.debug(vmList)
            except ServerError as e:
                raise RuntimeError(
                    _('Unable to get VM list from VDSM. Error: {m}').format(
                        m=str(e)))

            vms = set(vmList)
            if self.environment[ohostedcons.VMEnv.VM_UUID] not in vms:
                raise RuntimeError(
                    _('The engine VM is not running on this host'))

            self.logger.info('The engine VM is running on this host')
Beispiel #3
0
    def engine_vm_up_check(self):
        timeout = ohostedcons.Const.VM_LIVELINESS_CHECK_TIMEOUT
        vmstatus = vm_status.VmStatus()
        self.logger.info('Waiting for engine to start...')
        health_good = False
        while timeout >= 0:
            try:
                status = vmstatus.get_status()
                for host in status['all_host_stats'].values():
                    if 'engine-status' in host:
                        if '"health": "good"' in host['engine-status']:
                            health_good = True
                            break

            except (BrokerConnectionError, RuntimeError) as e:
                self.logger.debug(str(e))

            if health_good:
                self.logger.info('Engine is up')
                break

            time.sleep(5)
            timeout -= 5

            if timeout % 60 == 0:
                self.logger.info('Still waiting for engine to start...')

        if timeout < 0:
            self.logger.info(
                'Engine vm is still powering up, please check the vm\'s '
                'status using: \'hosted-engine --vm-status\''
            )
Beispiel #4
0
    def _validate_lm_volumes(self):
        """
        This method, if the relevant uuids aren't in the initial answerfile,
        will look for lockspace and metadata volumes on the shared
        storage identifying them by their description.
        We need to re-scan each time we run the upgrade flow since they
        could have been created in a previous upgrade attempt.
        If the volumes are not on disk, it triggers volume creation as for
        fresh deployments; volume creation code will also remove the previous
        file and create a new symlink to the volume using the same file name.
        """
        self.logger.info(_('Scanning for lockspace and metadata volumes'))
        cli = self.environment[ohostedcons.VDSMEnv.VDS_CLI]
        img = image.Image(
            self.environment[ohostedcons.StorageEnv.DOMAIN_TYPE],
            self.environment[ohostedcons.StorageEnv.SD_UUID],
        )
        img_list = img.get_images_list(cli)
        self.logger.debug('img list: {il}'.format(il=img_list))
        sdUUID = self.environment[ohostedcons.StorageEnv.SD_UUID]
        spUUID = ohostedcons.Const.BLANK_UUID
        for img in img_list:
            try:
                volumeslist = cli.StorageDomain.getVolumes(
                    imageID=img,
                    storagepoolID=spUUID,
                    storagedomainID=sdUUID,
                )
                self.logger.debug('volumeslist: {vl}'.format(vl=volumeslist))
            except ServerError as e:
                # avoid raising here, simply skip the unknown image
                self.logger.debug(
                    'Error fetching volumes for {image}: {message}'.format(
                        image=img,
                        message=str(e),
                    ))
                continue

            for vol_uuid in volumeslist['items']:
                try:
                    volumeinfo = cli.Volume.getInfo(
                        volumeID=vol_uuid,
                        imageID=img,
                        storagepoolID=spUUID,
                        storagedomainID=sdUUID,
                    )
                    self.logger.debug(volumeinfo)
                except ServerError as e:
                    # avoid raising here, simply skip the unknown volume
                    self.logger.debug(('Error fetching volume info '
                                       'for {volume}: {message}').format(
                                           volume=vol_uuid,
                                           message=str(e),
                                       ))
                    continue

                disk_description = volumeinfo['description']
                if disk_description == self.environment[
                        ohostedcons.SanlockEnv.LOCKSPACE_NAME] + '.lockspace':
                    self.environment[ohostedcons.StorageEnv.
                                     LOCKSPACE_VOLUME_UUID] = vol_uuid
                    self.environment[
                        ohostedcons.StorageEnv.LOCKSPACE_IMAGE_UUID] = img
                elif disk_description == self.environment[
                        ohostedcons.SanlockEnv.LOCKSPACE_NAME] + '.metadata':
                    self.environment[
                        ohostedcons.StorageEnv.METADATA_VOLUME_UUID] = vol_uuid
                    self.environment[
                        ohostedcons.StorageEnv.METADATA_IMAGE_UUID] = img

        if (self.environment[ohostedcons.StorageEnv.LOCKSPACE_VOLUME_UUID] and
                self.environment[ohostedcons.StorageEnv.METADATA_VOLUME_UUID]):
            self.logger.info(
                _('Lockspace and metadata volumes are already on the '
                  'HE storage domain'))
            return

        interactive = self.environment[
            ohostedcons.Upgrade.LM_VOLUMES_UPGRADE_PROCEED] is None
        if interactive:
            self.environment[
                ohostedcons.Upgrade.
                LM_VOLUMES_UPGRADE_PROCEED] = self.dialog.queryString(
                    name=ohostedcons.Confirms.LM_VOLUMES_UPGRADE_PROCEED,
                    note=_(
                        'This system was initially deployed with oVirt 3.4 '
                        'using file based metadata and lockspace area.\n'
                        'Now you have to upgrade to up to date structure '
                        'using this tool.\n'
                        'In order to do that please manually stop ovirt-ha-agent '
                        'and ovirt-ha-broker on all the other HE hosts '
                        '(but not this one). '
                        'At the end you of this procedure you can simply '
                        'manually upgrade ovirt-hosted-engine-ha and '
                        'restart ovirt-ha-agent and ovirt-ha-broker on all '
                        'the hosted-engine hosts.\n'
                        'Are you sure you want to continue? '
                        '(@VALUES@)[@DEFAULT@]: '),
                    prompt=True,
                    validValues=(_('Yes'), _('No')),
                    caseSensitive=False,
                    default=_('Yes')) == _('Yes').lower()
        if not self.environment[
                ohostedcons.Upgrade.LM_VOLUMES_UPGRADE_PROCEED]:
            raise otopicontext.Abort('Aborted by user')

        self.logger.info(
            _('Waiting for HA agents on other hosts to be stopped'))
        vmstatus = vm_status.VmStatus()
        ready = False
        while not ready:
            ready = True
            status = vmstatus.get_status()
            self.logger.debug('hosted-engine-status: {s}'.format(s=status))
            for h in status['all_host_stats']:
                host_id = status['all_host_stats'][h]['host-id']
                hostname = status['all_host_stats'][h]['hostname']
                if 'stopped' in status['all_host_stats'][h]:
                    stopped = status['all_host_stats'][h]['stopped']
                    if host_id == self.environment[
                            ohostedcons.StorageEnv.HOST_ID]:
                        if stopped:
                            self.logger.warning(
                                _('Please keep ovirt-ha-agent running '
                                  'on this host'))
                            ready = False
                    else:
                        if not stopped:
                            self.logger.warning(
                                _('ovirt-ha-agent is still active on host {h}, '
                                  'please stop it '
                                  '(it can require a few seconds).').format(
                                      h=hostname))
                            ready = False
                else:
                    self.logger.warning(
                        _("Ignoring inconsistent info for host {h}".format(
                            h=hostname, )))
            if not ready:
                time.sleep(2)

        self.environment[ohostedcons.Upgrade.UPGRADE_CREATE_LM_VOLUMES] = True
    def _check_upgrade_requirements(self):
        self.logger.info('Checking version requirements')
        upg = upgrade.Upgrade()
        if not upg.is_conf_file_uptodate():
            self.logger.error(
                _('Hosted-engine configuration didn\'t correctly reach 3.6 '
                  'level. Please successfully complete the upgrade to '
                  '3.6 before proceeding with this upgrade. '))
            raise RuntimeError(
                _('Unsupported hosted-engine configuration level'))
        self.logger.info(_('Checking metadata area'))
        vmstatus = vm_status.VmStatus()
        status = vmstatus.get_status()
        self.logger.debug('hosted-engine-status: {s}'.format(s=status))
        old_metadata = False
        for h in status['all_host_stats']:
            if 'stopped' not in status['all_host_stats'][h]:
                self.logger.error(
                    _('Metadata for host {h} is incompatible with this tool.\n'
                      'Before proceeding with this upgrade, '
                      'please correctly upgrade it to 3.6 '
                      'or clean its metadata area with\n'
                      ' \'hosted-engine --clean-metadata --host-id={id}\'\n'
                      'if decommissioned or not anymore involved in HE.').
                    format(
                        h=status['all_host_stats'][h]['hostname'],
                        id=status['all_host_stats'][h]['host-id'],
                    ))
                old_metadata = True
        if old_metadata:
            raise RuntimeError(_('Host with unsupported metadata area'))
        self.logger.info(
            _('Hosted-engine configuration is at a compatible level'))
        engine_api = engineapi.get_engine_api(self)
        self.logger.debug('Successfully connected to the engine')
        elements = engine_api.clusters.list() + engine_api.datacenters.list()
        for e in elements:
            if isinstance(e, brokers.DataCenter):
                element_t = 'datacenter'
            else:
                element_t = 'cluster'

            version = e.get_version()
            release = '{ma}.{mi}'.format(
                ma=version.major,
                mi=version.minor,
            )
            if release not in ohostedcons.Const.UPGRADE_REQUIRED_CLUSTER_V:
                self.logger.error(
                    _('{t} {name} is at version {release} which is not '
                      'supported by this upgrade flow. '
                      'Please fix it before upgrading.').format(
                          t=element_t.title(),
                          name=e.get_name(),
                          release=release,
                      ))
                raise RuntimeError(
                    _('Unsupported {t} level'.format(t=element_t)))
        self.logger.info(
            _('All the datacenters and clusters are at a compatible level'))
        e_major = engine_api.get_product_info().version.major
        e_minor = engine_api.get_product_info().version.minor
        if not e_major:
            # just for compatibility
            # see: bz#1405386
            e_major = engine_api.get_product_info().get_version().major
            e_minor = engine_api.get_product_info().get_version().minor
        if e_major is not None and e_minor is not None:
            self._e_version = '{ma}.{mi}'.format(
                ma=e_major,
                mi=e_minor,
            )