Пример #1
0
    def _wait_for_power_off(self, instance_name, time_limit):
        """Waiting for a VM to be in a disabled state.

           :return: True if the instance is shutdown within time_limit,
                    False otherwise.
        """

        desired_vm_states = [constants.HYPERV_VM_STATE_DISABLED]

        def _check_vm_status(instance_name):
            if self._get_vm_state(instance_name) in desired_vm_states:
                raise loopingcall.LoopingCallDone()

        periodic_call = loopingcall.FixedIntervalLoopingCall(
            _check_vm_status, instance_name)

        try:
            # add a timeout to the periodic call.
            periodic_call.start(interval=SHUTDOWN_TIME_INCREMENT)
            etimeout.with_timeout(time_limit, periodic_call.wait)
        except etimeout.Timeout:
            # VM did not shutdown in the expected time_limit.
            return False
        finally:
            # stop the periodic call, in case of exceptions or Timeout.
            periodic_call.stop()

        return True
Пример #2
0
            def _async_build_and_run_instance():
                # check dest compute service is alive
                utils.spawn_n(async_check_live)
                timer = loopingcall.FixedIntervalLoopingCall(_loop_check)
                timer.start(interval=1).wait()

                if not alive_dict['alive']:
                    LOG.warn(
                        '%s compute service seems down, revert instance '
                        'task state',
                        host_state,
                        instance=instance)
                    instance.task_state = None
                    instance.save()
                    return

                LOG.info('build instance on host %s',
                         host_state,
                         instance=instance)
                self.compute_rpcapi.sync_build_and_run_instance(
                    context,
                    instance=instance,
                    host=host_state,
                    image=image,
                    request_spec=request_spec,
                    filter_properties=filter_properties,
                    admin_password=None,
                    injected_files=jsonutils.loads(injected_files),
                    requested_networks=request_networks,
                    security_groups=security_groups,
                    block_device_mapping=bdms,
                    node=host_state,
                    limits=hosts[0]['limits'])
Пример #3
0
    def reboot(self, context, instance, network_info, reboot_type,
               block_device_info=None, bad_volumes_callback=None):
        """Reboot the specified instance.

        NOTE: Ironic does not support soft-off, so this method
              always performs a hard-reboot.
        NOTE: Unlike the libvirt driver, this method does not delete
              and recreate the instance; it preserves local state.

        :param context: The security context.
        :param instance: The instance object.
        :param network_info: Instance network information. Ignored by
            this driver.
        :param reboot_type: Either a HARD or SOFT reboot. Ignored by
            this driver.
        :param block_device_info: Info pertaining to attached volumes.
            Ignored by this driver.
        :param bad_volumes_callback: Function to handle any bad volumes
            encountered. Ignored by this driver.

        """
        node = _validate_instance_and_node(self.ironicclient, instance)
        self.ironicclient.call("node.set_power_state", node.uuid, 'reboot')

        timer = loopingcall.FixedIntervalLoopingCall(
                    self._wait_for_power_state,
                    self.ironicclient, instance, 'reboot')
        timer.start(interval=CONF.ironic.api_retry_interval).wait()
Пример #4
0
 def __init__(self, get_connection):
     super(VRouterVIFDriver, self).__init__(get_connection)
     self._vrouter_semaphore = eventlet.semaphore.Semaphore()
     self._vrouter_client = ContrailVRouterApi(
         doconnect=True, semaphore=self._vrouter_semaphore)
     timer = loopingcall.FixedIntervalLoopingCall(self._keep_alive)
     timer.start(interval=2)
Пример #5
0
    def _wait_for_node_reboot(self, nodename):
        """Wait for xCAT node boot to complete."""
        locals = {'errstr':''}

        def _wait_for_reboot():
            out,err = self._exec_xcat_command("nodestat %s" % nodename)
            if err:
                locals['errstr'] = _("Error returned when quering node status"
                           " for node %s:%s") % (nodename, err)
                LOG.warning(locals['errstr'])
                raise loopingcall.LoopingCallDone()

            if out:
                node,status = out.split(": ")
                status = status.strip()
                if status == "sshd":
                    LOG.info(_("Rebooting node %s completed.")
                             % nodename)
                    raise loopingcall.LoopingCallDone()

            if (CONF.xcat.reboot_timeout and
                    timeutils.utcnow() > expiration):
                locals['errstr'] = _("Timeout while waiting for"
                           " rebooting node %s.") % nodename
                LOG.warning(locals['errstr'])
                raise loopingcall.LoopingCallDone()

        expiration = timeutils.utcnow() + datetime.timedelta(
                seconds=CONF.xcat.reboot_timeout)
        timer = loopingcall.FixedIntervalLoopingCall(_wait_for_reboot)
        # default check every 5 seconds
        timer.start(interval=CONF.xcat.reboot_checking_interval).wait()

        if locals['errstr']:
            raise exception.xCATRebootFailure(locals['errstr'])
Пример #6
0
    def start(self):
        """
        This method retrieves all services from PowerVC and for each
        service it creates a local nova-compute service.
        """

        try:
            remote_services = self._get_filtered_remote_services()

            for remote_service in remote_services:
                eventlet.greenthread.sleep(0)
                self.new_compute_service(remote_service)

            if self.auto_refresh:
                refresher = loopingcall.FixedIntervalLoopingCall(self.refresh)
                refresher.start(
                    interval=CONF.powervc.hypervisor_refresh_interval)
            LOG.info(_('The PowerVC compute service manager is running.'))

            self.running = True
        except Exception:
            LOG.exception("exception during startup.  Stopping compute"
                          "driver")
            traceback.print_exc()
            sys.exit(1)
Пример #7
0
    def wait_task_done(self, task_uri, interval=3):
        """

        :param task_uri:
        :param interval:
        :return:
        """
        ret = {'success': False, 'reason': None}

        def _wait_done():
            """
            wait task result
            """

            task = self.get_task(task_uri)

            if task['status'] == "success":
                LOG.info(_("Task [%s] is successfully." % task_uri))
                ret['success'] = True
                raise loopingcall.LoopingCallDone()
            elif task['status'] == "failed":
                LOG.info(_("Task [%s] is failed, the reason is %s."), task_uri,
                         task['reasonDes'])
                ret['reason'] = task['reasonDes']
                raise loopingcall.LoopingCallDone()
            else:
                LOG.info(_("Task [%s] is running, the progress is %s."),
                         task_uri, task['progress'])

        timer = loopingcall.FixedIntervalLoopingCall(_wait_done)
        timer.start(interval=interval).wait()
        return ret['success'], ret['reason']
Пример #8
0
    def cleanup_volumes(self, instance):
        def _cleanup_vol(ioctx, volume, retryctx):
            try:
                rbd.RBD().remove(client.ioctx, volume)
                raise loopingcall.LoopingCallDone(retvalue=False)
            except (rbd.ImageBusy, rbd.ImageHasSnapshots):
                LOG.warn(
                    _LW('rbd remove %(volume)s in pool %(pool)s '
                        'failed'), {
                            'volume': volume,
                            'pool': self.pool
                        })
            retryctx['retries'] -= 1
            if retryctx['retries'] <= 0:
                raise loopingcall.LoopingCallDone()

        with RADOSClient(self, self.pool) as client:

            def belongs_to_instance(disk):
                return disk.startswith(instance.uuid)

            volumes = rbd.RBD().list(client.ioctx)
            for volume in filter(belongs_to_instance, volumes):
                # NOTE(danms): We let it go for ten seconds
                retryctx = {'retries': 10}
                timer = loopingcall.FixedIntervalLoopingCall(
                    _cleanup_vol, client.ioctx, volume, retryctx)
                timed_out = timer.start(interval=1).wait()
                if timed_out:
                    # NOTE(danms): Run this again to propagate the error, but
                    # if it succeeds, don't raise the loopingcall exception
                    try:
                        _cleanup_vol(client.ioctx, volume, retryctx)
                    except loopingcall.LoopingCallDone:
                        pass
Пример #9
0
def wait_for_power_state(instance, power_state, time_limit):
    """Waiting for a virtual machine to be in required power state.

    :param instance:    nova.objects.instance.Instance
    :param power_state: nova.compute.power_state
    :param time_limit:  (int) time limit for this task

    :return: True if the instance is in required power state
             within time_limit, False otherwise.
    """

    def _check_power_state(instance):
        current_state = get_power_state(instance)
        LOG.debug("Wait for soft shutdown: (%s, %s)", current_state,
                  power_state)
        if current_state == power_state:
            raise loopingcall.LoopingCallDone()
    response = True
    periodic_call = loopingcall.FixedIntervalLoopingCall(_check_power_state,
                                                         instance)
    try:
        # add a timeout to the periodic call.
        periodic_call.start(interval=constants.SHUTDOWN_RETRY_INTERVAL)
        etimeout.with_timeout(time_limit, periodic_call.wait)
    except etimeout.Timeout:
        # Virtual machine did not shutdown in the expected time_limit.
        response = False

    finally:
        # Stop the periodic call, in case of exceptions or Timeout.
        periodic_call.stop()

    return response
Пример #10
0
    def _poll_for_lpar_status(self, instance_name, status, operation,
                            timeout=constants.POWERVM_LPAR_OPERATION_TIMEOUT):
        """Polls until the LPAR with the given name reaches the given status.

        :param instance_name: LPAR instance name
        :param status: Poll until the given LPAR status is reached
        :param operation: The operation being performed, e.g. 'stop_lpar'
        :param timeout: The number of seconds to wait.
        :raises: PowerVMLPARInstanceNotFound
        :raises: PowerVMLPAROperationTimeout
        :raises: InvalidParameterValue
        """
        # make sure it's a valid status
        if (status == constants.POWERVM_NOSTATE or
                not status in constants.POWERVM_POWER_STATE):
            msg = _("Invalid LPAR state: %s") % status
            raise n_exc.InvalidParameterValue(err=msg)

        # raise the given timeout exception if the loop call doesn't complete
        # in the specified timeout
        timeout_exception = exception.PowerVMLPAROperationTimeout(
                                                operation=operation,
                                                instance_name=instance_name)
        with eventlet_timeout.Timeout(timeout, timeout_exception):
            def _wait_for_lpar_status(instance_name, status):
                """Called at an interval until the status is reached."""
                lpar_obj = self.get_lpar(instance_name)
                if lpar_obj['state'] == status:
                    raise loopingcall.LoopingCallDone()

            timer = loopingcall.FixedIntervalLoopingCall(_wait_for_lpar_status,
                                                         instance_name, status)
            timer.start(interval=1).wait()
Пример #11
0
    def power_on(self,
                 context,
                 instance,
                 network_info,
                 block_device_info=None):
        """Power on the specified instance.

        NOTE: Unlike the libvirt driver, this method does not delete
              and recreate the instance; it preserves local state.

        :param context: The security context.
        :param instance: The instance object.
        :param network_info: Instance network information. Ignored by
            this driver.
        :param block_device_info: Instance block device
            information. Ignored by this driver.

        """
        node = _validate_instance_and_node(self.ironicclient, instance)
        self.ironicclient.call("node.set_power_state", node.uuid, 'on')

        timer = loopingcall.FixedIntervalLoopingCall(
            self._wait_for_power_state, self.ironicclient, instance,
            'power on')
        timer.start(interval=CONF.ironic.api_retry_interval).wait()
Пример #12
0
    def _power_off(self):
        """Turn the power to this node OFF."""
        def _wait_for_power_off():
            """Called at an interval until the node's power is off."""

            if self.is_power_on() is False:
                self.state = baremetal_states.DELETED
                raise loopingcall.LoopingCallDone()
            if self.retries > CONF.baremetal.ipmi_power_retry:
                LOG.error(
                    _("IPMI power off failed after %d tries") %
                    (CONF.baremetal.ipmi_power_retry))
                self.state = baremetal_states.ERROR
                raise loopingcall.LoopingCallDone()
            try:
                self.retries += 1
                if not self.power_off_called:
                    self._exec_ipmitool("power off")
                    self.power_off_called = True
            except Exception:
                LOG.exception(_("IPMI power off failed"))

        self.retries = 0
        self.power_off_called = False
        timer = loopingcall.FixedIntervalLoopingCall(_wait_for_power_off)
        timer.start(interval=1.0).wait()
Пример #13
0
 def __init__(self):
     super(ContrailVIFDriver, self).__init__()
     self._agent_alive = False
     self._agent_connected = False
     self._port_dict = {}
     self._protocol = None
     timer = loopingcall.FixedIntervalLoopingCall(self._keep_alive)
     timer.start(interval=2)
Пример #14
0
 def add_timer(self,
               interval,
               callback,
               initial_delay=None,
               *args,
               **kwargs):
     pulse = loopingcall.FixedIntervalLoopingCall(callback, *args, **kwargs)
     pulse.start(interval=interval, initial_delay=initial_delay)
     self.timers.append(pulse)
Пример #15
0
    def _handoff_recv(self, base_vm_paths, base_hashvalue,
                      handoff_recv_datafile, launch_diskpath,
                      launch_memorypath):
        # data structure for handoff receiving
        handoff_ds_recv = handoff.HandoffDataRecv()
        handoff_ds_recv.save_data(base_vm_paths, base_hashvalue,
                                  launch_diskpath, launch_memorypath)
        handoff_ds_recv.to_file(handoff_recv_datafile)

        LOG.debug("start handoff recv process")
        cmd = [
            "/usr/local/bin/handoff-server-proc", "-d",
            "%s" % handoff_recv_datafile
        ]
        LOG.debug("subprocess: %s" % cmd)
        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, close_fds=True)
        stdout_buf = StringIO.StringIO()

        def _wait_for_handoff_recv(print_log=True):
            """Called at an interval until VM synthesis finishes."""
            returncode = proc.poll()
            if returncode is None:
                # keep record stdout
                LOG.debug("waiting for finishing handoff recv")
                in_ready, _, _ = select.select([proc.stdout], [], [])
                try:
                    buf = os.read(proc.stdout.fileno(), 1024 * 100)
                    if print_log:
                        LOG.debug(buf)
                    stdout_buf.write(buf)
                except OSError as e:
                    if e.errno == errno.EAGAIN or e.errno == errno.EWOULDBLOCK:
                        return
            else:
                # handoff finishes. Read reamining stdout
                in_ready, _, _ = select.select([proc.stdout], [], [], 0.1)
                buf = proc.stdout.read()
                stdout_buf.write(buf)
                raise loopingcall.LoopingCallDone()

        timer = loopingcall.FixedIntervalLoopingCall(_wait_for_handoff_recv)
        timer.start(interval=0.5).wait()
        LOG.info("Handoff recv finishes")
        returncode = proc.poll()
        if returncode is not 0:
            msg = "Failed to receive handoff data"
            raise handoff.HandoffError(msg)

        # parse output: this will be fixed at cloudlet deamon
        keyword, disksize, memorysize, disk_overlay_map, memory_overlay_map =\
            stdout_buf.getvalue().split("\n")[-1].split("\t")
        if keyword.lower() != "openstack":
            raise handoff.HandoffError("Failed to parse returned data")
        return disksize, memorysize, disk_overlay_map, memory_overlay_map
Пример #16
0
 def _wait_for_task(self, instance_uuid, task_ref):
     """
     Return a Deferred that will give the result of the given task.
     The task is polled until it completes.
     """
     done = event.Event()
     loop = loopingcall.FixedIntervalLoopingCall(self._poll_task,
                                                 instance_uuid,
                                                 task_ref, done)
     loop.start(CONF.vmware.task_poll_interval)
     ret_val = done.wait()
     loop.stop()
     return ret_val
Пример #17
0
    def connect_volume(self, connection_info, mount_device):
        shelf = connection_info['data']['target_shelf']
        lun = connection_info['data']['target_lun']
        aoedev = 'e%s.%s' % (shelf, lun)
        aoedevpath = '/dev/etherd/%s' % (aoedev)

        if os.path.exists(aoedevpath):
            # NOTE(jbr_): If aoedevpath already exists, revalidate the LUN.
            self._aoe_revalidate(aoedev)
        else:
            # NOTE(jbr_): If aoedevpath does not exist, do a discover.
            self._aoe_discover()

        #NOTE(jbr_): Device path is not always present immediately
        def _wait_for_device_discovery(aoedevpath, mount_device):
            tries = self.tries
            if os.path.exists(aoedevpath):
                raise loopingcall.LoopingCallDone()

            if self.tries >= CONF.num_aoe_discover_tries:
                raise exception.NovaException(
                    _("AoE device not found at %s") % (aoedevpath))
            LOG.warn(
                _("AoE volume not yet found at: %(aoedevpath)s. "
                  "Try number: %(tries)s"), {
                      'aoedevpath': aoedevpath,
                      'tries': tries
                  })

            self._aoe_discover()
            self.tries = self.tries + 1

        self.tries = 0
        timer = loopingcall.FixedIntervalLoopingCall(
            _wait_for_device_discovery, aoedevpath, mount_device)
        timer.start(interval=2).wait()

        tries = self.tries
        if tries != 0:
            LOG.debug(
                _("Found AoE device %(aoedevpath)s "
                  "(after %(tries)s rediscover)"), {
                      'aoedevpath': aoedevpath,
                      'tries': tries
                  })

        conf = super(LibvirtAOEVolumeDriver,
                     self).connect_volume(connection_info, mount_device)
        conf.source_type = "block"
        conf.source_path = aoedevpath
        return conf
Пример #18
0
    def _unprovision(self, ironicclient, instance, node):
        """This method is called from destroy() to unprovision
        already provisioned node after required checks.
        """
        try:
            ironicclient.call("node.set_provision_state", node.uuid, "deleted")
        except Exception as e:
            # if the node is already in a deprovisioned state, continue
            # This should be fixed in Ironic.
            # TODO(deva): This exception should be added to
            #             python-ironicclient and matched directly,
            #             rather than via __name__.
            if getattr(e, '__name__', None) != 'InstanceDeployFailure':
                raise

        # using a dict because this is modified in the local method
        data = {'tries': 0}

        def _wait_for_provision_state():
            node = _validate_instance_and_node(ironicclient, instance)
            if node.provision_state in (ironic_states.NOSTATE,
                                        ironic_states.CLEANING,
                                        ironic_states.CLEANFAIL,
                                        ironic_states.AVAILABLE):
                # From a user standpoint, the node is unprovisioned. If a node
                # gets into CLEANFAIL state, it must be fixed in Ironic, but we
                # can consider the instance unprovisioned.
                LOG.debug(
                    "Ironic node %(node)s is in state %(state)s, "
                    "instance is now unprovisioned.",
                    dict(node=node.uuid, state=node.provision_state),
                    instance=instance)
                raise loopingcall.LoopingCallDone()

            if data['tries'] >= CONF.ironic.api_max_retries:
                msg = (_("Error destroying the instance on node %(node)s. "
                         "Provision state still '%(state)s'.") % {
                             'state': node.provision_state,
                             'node': node.uuid
                         })
                LOG.error(msg)
                raise exception.NovaException(msg)
            else:
                data['tries'] += 1

            _log_ironic_polling('unprovision', node, instance)

        # wait for the state transition to finish
        timer = loopingcall.FixedIntervalLoopingCall(_wait_for_provision_state)
        timer.start(interval=CONF.ironic.api_retry_interval).wait()
Пример #19
0
 def _wait_for_task(self, task_ref):
     """Return a Deferred that will give the result of the given task.
     The task is polled until it completes.
     """
     done = event.Event()
     loop = loopingcall.FixedIntervalLoopingCall(self._poll_task,
                                                 task_ref, done)
     loop.start(CONF.vmware.task_poll_interval)
     try:
         ret_val = done.wait()
     except Exception:
         raise
     finally:
         self._stop_loop(loop)
     return ret_val
Пример #20
0
    def activate_node(self, context, node, instance):
        """Wait for PXE deployment to complete."""

        locals = {'error': '', 'started': False}

        def _wait_for_deploy():
            """Called at an interval until the deployment completes."""
            try:
                row = db.bm_node_get(context, node['id'])
                if instance['uuid'] != row.get('instance_uuid'):
                    locals['error'] = _("Node associated with another instance"
                                        " while waiting for deploy of %s")
                    raise loopingcall.LoopingCallDone()

                status = row.get('task_state')
                if (status == baremetal_states.DEPLOYING
                        and locals['started'] == False):
                    LOG.info(
                        _("PXE deploy started for instance %s") %
                        instance['uuid'])
                    locals['started'] = True
                elif status in (baremetal_states.DEPLOYDONE,
                                baremetal_states.ACTIVE):
                    LOG.info(
                        _("PXE deploy completed for instance %s") %
                        instance['uuid'])
                    raise loopingcall.LoopingCallDone()
                elif status == baremetal_states.DEPLOYFAIL:
                    locals['error'] = _("PXE deploy failed for instance %s")
            except exception.NodeNotFound:
                locals['error'] = _("Baremetal node deleted while waiting "
                                    "for deployment of instance %s")

            if (CONF.baremetal.pxe_deploy_timeout
                    and timeutils.utcnow() > expiration):
                locals['error'] = _("Timeout reached while waiting for "
                                    "PXE deploy of instance %s")
            if locals['error']:
                raise loopingcall.LoopingCallDone()

        expiration = timeutils.utcnow() + datetime.timedelta(
            seconds=CONF.baremetal.pxe_deploy_timeout)
        timer = loopingcall.FixedIntervalLoopingCall(_wait_for_deploy)
        timer.start(interval=1).wait()

        if locals['error']:
            raise exception.InstanceDeployFailure(locals['error'] %
                                                  instance['uuid'])
Пример #21
0
    def join(self, member_id, group_id, service=None):
        """Join the given service with it's group."""

        msg = _('DB_Driver: join new ServiceGroup member %(member_id)s to '
                    'the %(group_id)s group, service = %(service)s')
        LOG.debug(msg, locals())
        if service is None:
            raise RuntimeError(_('service is a mandatory argument for DB based'
                                 ' ServiceGroup driver'))
        report_interval = service.report_interval
        if report_interval:
            pulse = loopingcall.FixedIntervalLoopingCall(self._report_state,
                                                         service)
            pulse.start(interval=report_interval,
                        initial_delay=report_interval)
            return pulse
Пример #22
0
    def _unprovision(self, icli, instance, node):
        """This method is called from destroy() to unprovision
        already provisioned node after required checks.
        """
        try:
            self._retry_if_service_is_unavailable(
                icli.node.set_provision_state, node.uuid, 'deleted')
        except MaximumRetriesReached:
            msg = (_("Error triggering the unprovisioning of the node %s") %
                   node.uuid)
            LOG.error(msg)
            raise exception.NovaException(msg)
        except Exception as e:
            # if the node is already in a deprovisioned state, continue
            # This should be fixed in Ironic.
            # TODO(deva): This exception should be added to
            #             python-ironicclient and matched directly,
            #             rather than via __name__.
            if getattr(e, '__name__', None) == 'InstanceDeployFailure':
                pass
            else:
                raise

        def _wait_for_provision_state():
            try:
                node = icli.node.get_by_instance_uuid(instance['uuid'])
            except ironic_exception.HTTPNotFound:
                raise exception.InstanceNotFound(instance_id=instance['uuid'])

            if not node.provision_state:
                raise loopingcall.LoopingCallDone()

            if self.tries >= CONF.ironic.api_max_retries:
                msg = (_("Error destroying the instance on node %(node)s. "
                         "Provision state still '%(state)s'.") % {
                             'state': node.provision_state,
                             'node': node.uuid
                         })
                LOG.error(msg)
                raise exception.NovaException(msg)
            else:
                self.tries += 1

        # wait for the state transition to finish
        self.tries = 0
        timer = loopingcall.FixedIntervalLoopingCall(_wait_for_provision_state)
        timer.start(interval=CONF.ironic.api_retry_interval).wait()
Пример #23
0
    def _retry_if_service_is_unavailable(self, func, *args):
        """Rety the request if the API returns 409 (Conflict)."""
        def _request_api():
            try:
                func(*args)
                raise loopingcall.LoopingCallDone()
            except ironic_exception.HTTPServiceUnavailable:
                pass

            if self.tries >= CONF.ironic.api_max_retries:
                raise MaximumRetriesReached()
            else:
                self.tries += 1

        self.tries = 0
        timer = loopingcall.FixedIntervalLoopingCall(_request_api)
        timer.start(interval=CONF.ironic.api_retry_interval).wait()
Пример #24
0
def periodic_flavor_sync(ctx, driver, scg_id_list):
    """
        Periodically update the flavors from PowerVC.
        A default time of 300 seconds is specified for the refresh interval.
        if the refresh interval is set to 0, then flavors are not refreshed.
        """
    sync_interval = CONF.powervc.flavor_sync_interval

    if sync_interval is None or sync_interval == 0:
        return

    def flavors_sync(driver, scg_id_list):
        FlavorSync(driver, scg_id_list).synchronize_flavors(ctx)
        LOG.debug('Flavors synchronization completed')

    sync_flavors = loopingcall.FixedIntervalLoopingCall(
        flavors_sync, driver, scg_id_list)
    sync_flavors.start(interval=sync_interval, initial_delay=sync_interval)
Пример #25
0
    def _unprovision(self, icli, instance, node):
        """This method is called from destroy() to unprovision
        already provisioned node after required checks.
        """
        try:
            icli.call("node.set_provision_state", node.uuid, "deleted")
        except Exception as e:
            # if the node is already in a deprovisioned state, continue
            # This should be fixed in Ironic.
            # TODO(deva): This exception should be added to
            #             python-ironicclient and matched directly,
            #             rather than via __name__.
            if getattr(e, '__name__', None) == 'InstanceDeployFailure':
                pass
            else:
                raise

        # using a dict because this is modified in the local method
        data = {'tries': 0}

        def _wait_for_provision_state():
            try:
                node = icli.call("node.get_by_instance_uuid", instance['uuid'])
            except ironic_exception.NotFound:
                raise exception.InstanceNotFound(instance_id=instance['uuid'])

            if not node.provision_state:
                raise loopingcall.LoopingCallDone()

            if data['tries'] >= CONF.ironic.api_max_retries:
                msg = (_("Error destroying the instance on node %(node)s. "
                         "Provision state still '%(state)s'.") % {
                             'state': node.provision_state,
                             'node': node.uuid
                         })
                LOG.error(msg)
                raise exception.NovaException(msg)
            else:
                data['tries'] += 1

        # wait for the state transition to finish
        timer = loopingcall.FixedIntervalLoopingCall(_wait_for_provision_state)
        timer.start(interval=CONF.ironic.api_retry_interval).wait()
Пример #26
0
    def _wait_for_image_state(self, ami_id, desired_state):
        """Timer to wait for the image/snapshot to reach a desired state
        :params:ami_id: correspoding image id in Amazon
        :params:desired_state: the desired new state of the image to be in.
        """
        def _wait_for_state():
            """Called at an interval until the AMI image is available."""
            try:
                images = self.ec2_conn.get_all_images(image_ids=[ami_id], owners=None,
                                                      executable_by=None, filters=None, dry_run=None)
                state = images[0].state
                # LOG.info("\n\n\nImage id = %s" % ami_id + ", state = %s\n\n\n" % state)
                if state == desired_state:
                    LOG.info("Image has changed state to %s." % desired_state)
                    raise loopingcall.LoopingCallDone()
            except boto_exc.EC2ResponseError:
                pass

        timer = loopingcall.FixedIntervalLoopingCall(_wait_for_state)
        timer.start(interval=0.5).wait()
Пример #27
0
    def _power_on(self):
        """Turn the power to this node ON."""
        def _wait_for_power_on():
            """Called at an interval until the node's power is on."""

            if self.is_power_on():
                self.state = baremetal_states.ACTIVE
                raise loopingcall.LoopingCallDone()
            if self.retries > CONF.baremetal.ipmi_power_retry:
                self.state = baremetal_states.ERROR
                raise loopingcall.LoopingCallDone()
            try:
                self.retries += 1
                self._exec_ipmitool("power on")
            except Exception:
                LOG.exception(_("IPMI power on failed"))

        self.retries = 0
        timer = loopingcall.FixedIntervalLoopingCall(_wait_for_power_on)
        timer.start(interval=0.5).wait()
Пример #28
0
    def power_off(self, instance, timeout=0, retry_interval=0):
        """Power off the specified instance.

        NOTE: Ironic does not support soft-off, so this method ignores
              timeout and retry_interval parameters.
        NOTE: Unlike the libvirt driver, this method does not delete
              and recreate the instance; it preserves local state.

        :param instance: The instance object.
        :param timeout: time to wait for node to shutdown. Ignored by
            this driver.
        :param retry_interval: How often to signal node while waiting
            for it to shutdown. Ignored by this driver.
        """
        icli = client_wrapper.IronicClientWrapper()
        node = _validate_instance_and_node(icli, instance)
        icli.call("node.set_power_state", node.uuid, 'off')

        timer = loopingcall.FixedIntervalLoopingCall(
            self._wait_for_power_state, icli, instance, 'power off')
        timer.start(interval=CONF.ironic.api_retry_interval).wait()
Пример #29
0
            def _async_reschedule():
                # check dest compute service is alive
                utils.spawn_n(async_check_live)
                timer = loopingcall.FixedIntervalLoopingCall(_loop_check)
                timer.start(interval=1).wait()

                if not alive_dict['alive']:
                    LOG.warn(
                        '%s compute service seems down, revert instance '
                        'task state',
                        host_state,
                        instance=instance)
                    instance.task_state = None
                    instance.save()
                    return

                LOG.info('reschedule instance to host %s',
                         host_state,
                         instance=instance)
                try:
                    self.compute_rpcapi.sync_reschedule_instance(
                        context,
                        instance=instance,
                        new_pass=None,
                        injected_files=jsonutils.loads(injected_files),
                        image_ref=image_ref,
                        orig_image_ref=orig_image_ref,
                        orig_sys_metadata=None,
                        bdms=bdms,
                        host=host_state,
                        filter_properties=filter_properties)
                except Exception as e:
                    LOG.error(_LE('reschedule call failed: %s'), e)
                    self.db.instance_update(context,
                                            instance.uuid,
                                            task_state=None)
Пример #30
0
    def connect_volume(self, connection_info, disk_info):
        """Attach the volume to instance_name."""
        fc_properties = connection_info['data']
        mount_device = disk_info["dev"]

        ports = fc_properties['target_wwn']
        wwns = []
        # we support a list of wwns or a single wwn
        if isinstance(ports, list):
            for wwn in ports:
                wwns.append(wwn)
        elif isinstance(ports, str):
            wwns.append(ports)

        # We need to look for wwns on every hba
        # because we don't know ahead of time
        # where they will show up.
        hbas = virtutils.get_fc_hbas_info()
        host_devices = []
        for hba in hbas:
            pci_num = self._get_pci_num(hba)
            if pci_num is not None:
                for wwn in wwns:
                    target_wwn = "0x%s" % wwn.lower()
                    host_device = ("/dev/disk/by-path/pci-%s-fc-%s-lun-%s" %
                                   (pci_num, target_wwn,
                                    fc_properties.get('target_lun', 0)))
                    host_devices.append(host_device)

        if len(host_devices) == 0:
            # this is empty because we don't have any FC HBAs
            msg = _("We are unable to locate any Fibre Channel devices")
            raise exception.NovaException(msg)

        # The /dev/disk/by-path/... node is not always present immediately
        # We only need to find the first device.  Once we see the first device
        # multipath will have any others.
        def _wait_for_device_discovery(host_devices, mount_device):
            tries = self.tries
            for device in host_devices:
                LOG.debug(_("Looking for Fibre Channel dev %(device)s"),
                          {'device': device})
                if os.path.exists(device):
                    self.host_device = device
                    # get the /dev/sdX device.  This is used
                    # to find the multipath device.
                    self.device_name = os.path.realpath(device)
                    raise loopingcall.LoopingCallDone()

            if self.tries >= CONF.num_iscsi_scan_tries:
                msg = _("Fibre Channel device not found.")
                raise exception.NovaException(msg)

            LOG.warn(
                _("Fibre volume not yet found at: %(mount_device)s. "
                  "Will rescan & retry.  Try number: %(tries)s"), {
                      'mount_device': mount_device,
                      'tries': tries
                  })

            linuxscsi.rescan_hosts(hbas)
            self.tries = self.tries + 1

        self.host_device = None
        self.device_name = None
        self.tries = 0
        timer = loopingcall.FixedIntervalLoopingCall(
            _wait_for_device_discovery, host_devices, mount_device)
        timer.start(interval=2).wait()

        tries = self.tries
        if self.host_device is not None and self.device_name is not None:
            LOG.debug(
                _("Found Fibre Channel volume %(mount_device)s "
                  "(after %(tries)s rescans)"), {
                      'mount_device': mount_device,
                      'tries': tries
                  })

        # see if the new drive is part of a multipath
        # device.  If so, we'll use the multipath device.
        mdev_info = linuxscsi.find_multipath_device(self.device_name)
        if mdev_info is not None:
            LOG.debug(
                _("Multipath device discovered %(device)s") %
                {'device': mdev_info['device']})
            device_path = mdev_info['device']
            connection_info['data']['devices'] = mdev_info['devices']
            connection_info['data']['multipath_id'] = mdev_info['id']
        else:
            # we didn't find a multipath device.
            # so we assume the kernel only sees 1 device
            device_path = self.host_device
            device_info = linuxscsi.get_device_info(self.device_name)
            connection_info['data']['devices'] = [device_info]

        conf = super(LibvirtFibreChannelVolumeDriver,
                     self).connect_volume(connection_info, disk_info)

        conf.source_type = "block"
        conf.source_path = device_path
        return conf