Example #1
0
    def do_update(self, context, new_profile_id):
        if not new_profile_id:
            raise exception.ProfileNotSpecified()

        if new_profile_id == self.profile_id:
            return True

        if not self.physical_id:
            return False

        # Check if profile types match
        old_profile = db_api.get_profile(context, self.profile_id)
        new_profile = db_api.get_profile(context, new_profile_id)
        if old_profile.type != new_profile.type:
            event_mod.warning(_LW('Node cannot be updated to a different '
                                  'profile type (%(oldt)s->%(newt)s)') %
                              {'oldt': old_profile.type,
                               'newt': new_profile.type})
            return False

        res = profile_base.update_object(self, new_profile_id)
        if res:
            self.rt['profile'] = profile_base.load(context,
                                                   new_profile_id)
            self.profile_id = new_profile_id
            self.updated_time = datetime.datetime.utcnow()
            self.store()

        return res
Example #2
0
    def do_update(self, context, new_profile_id, **kwargs):
        '''Additional logic at the beginning of cluster updating progress.

        Check profile and set cluster status to UPDATING.
        '''
        # Profile type checking is done here because the do_update logic can
        # be triggered from API or Webhook
        if not new_profile_id:
            raise exception.ProfileNotSpecified()

        if new_profile_id == self.profile_id:
            return True

        new_profile = db_api.get_profile(context, new_profile_id)
        if not new_profile:
            event_mod.warning(context, self, 'update',
                              _LW('Cluster cannot be updated to a profile '
                                  'that does not exists'))
            return False

        # Check if profile types match
        old_profile = db_api.get_profile(context, self.profile_id)
        if old_profile.type != new_profile.type:
            event_mod.warning(context, self, 'update',
                              _LW('Cluster cannot be updated to a different '
                                  'profile type (%(oldt)s->%(newt)s)') % {
                                      'oldt': old_profile.type,
                                      'newt': new_profile.type})
            return False

        self.set_status(self.UPDATING)
        return True
Example #3
0
    def set_status(self, result, reason=None):
        """Set action status based on return value from execute."""

        timestamp = wallclock()

        if result == self.RES_OK:
            status = self.SUCCEEDED
            ao.Action.mark_succeeded(self.context, self.id, timestamp)

        elif result == self.RES_ERROR:
            status = self.FAILED
            ao.Action.mark_failed(self.context, self.id, timestamp,
                                  reason or 'ERROR')

        elif result == self.RES_TIMEOUT:
            status = self.FAILED
            ao.Action.mark_failed(self.context, self.id, timestamp,
                                  reason or 'TIMEOUT')

        elif result == self.RES_CANCEL:
            status = self.CANCELLED
            ao.Action.mark_cancelled(self.context, self.id, timestamp)

        elif result == self.RES_LIFECYCLE_COMPLETE:
            status = self.SUCCEEDED
            ao.Action.mark_ready(self.context, self.id, timestamp)

        else:  # result == self.RES_RETRY:
            retries = self.data.get('retries', 0)
            # Action failed at the moment, but can be retried
            # retries time is configurable
            if retries < cfg.CONF.lock_retry_times:
                status = self.READY
                retries += 1

                self.data.update({'retries': retries})
                ao.Action.abandon(self.context, self.id, {'data': self.data})
                # sleep for a while
                eventlet.sleep(cfg.CONF.lock_retry_interval)
                dispatcher.start_action(self.id)
            else:
                status = self.RES_ERROR
                if not reason:
                    reason = ('Exceeded maximum number of retries (%d)'
                              '') % cfg.CONF.lock_retry_times
                ao.Action.mark_failed(self.context, self.id, timestamp, reason)

        if status == self.SUCCEEDED:
            EVENT.info(self, consts.PHASE_END, reason or 'SUCCEEDED')
        elif status == self.READY:
            EVENT.warning(self, consts.PHASE_ERROR, reason or 'RETRY')
        else:
            EVENT.error(self, consts.PHASE_ERROR, reason or 'ERROR')

        self.status = status
        self.status_reason = reason
Example #4
0
    def member_add(self, node, lb_id, pool_id, port, subnet):
        """Add a member to Neutron lbaas pool.

        :param node: A node object to be added to the specified pool.
        :param lb_id: The ID of the loadbalancer.
        :param pool_id: The ID of the pool for receiving the node.
        :param port: The port for the new LB member to be created.
        :param subnet: The subnet to be used by the new LB member.
        :returns: The ID of the new LB member or None if errors occurred.
        """
        addresses = self._get_node_address(node, version=4)
        if not addresses:
            LOG.error(_LE('Node (%(n)s) does not have valid IPv4 address.'),
                      {'n': node.id})
            return None

        try:
            subnet_obj = self.nc().subnet_get(subnet)
            net_id = subnet_obj.network_id
            net = self.nc().network_get(net_id)
        except exception.InternalError as ex:
            resource = 'subnet' if subnet in ex.message else 'network'
            msg = _LE('Failed in getting %(resource)s: %(msg)s.'
                      ) % {'resource': resource, 'msg': six.text_type(ex)}
            LOG.exception(msg)
            event.warning(oslo_context.get_current(), self,
                          resource.upper()+'_GET', 'ERROR', msg)
            return None
        net_name = net.name

        if net_name not in addresses:
            LOG.error(_LE('Node is not in subnet %(subnet)s'),
                      {'subnet': subnet})
            return None

        address = addresses[net_name]
        try:
            member = self.nc().pool_member_create(pool_id, address, port,
                                                  subnet_obj.id)
        except exception.InternalError as ex:
            msg = _LE('Failed in creating lb pool member: %s.'
                      ) % six.text_type(ex)
            LOG.exception(msg)
            event.warning(oslo_context.get_current(), self,
                          'POOL_MEMBER_CREATE', 'ERROR', msg)
            return None
        res = self._wait_for_lb_ready(lb_id)
        if res is False:
            LOG.error(_LE('Failed in creating pool member (%s).') % member.id)
            return None

        return member.id
Example #5
0
 def _handle_exception(self, context, action, status, exception):
     msg = six.text_type(exception)
     event_mod.warning(context, self, action, status, msg)
     self.physical_id = exception.kwargs.get('resource_id', None)
     if self.physical_id:
         reason = _('Profile failed in %(action)s resource (%(id)s) due '
                    'to: %(msg)s') % {'action': action[:-1] + 'ing',
                                      'id': self.physical_id, 'msg': msg}
     else:
         # Exception happens before physical node creatin started.
         reason = _('Profile failed in creating node due to: %(msg)s') % {
             'msg': msg}
     self.set_status(context, self.ERROR, reason)
     self.store(context)
Example #6
0
 def _handle_exception(self, context, action, status, exception):
     msg = six.text_type(exception)
     event_mod.warning(context, self, action, status, msg)
     self.physical_id = exception.kwargs.get('resource_id', None)
     if self.physical_id:
         reason = _('Profile failed in %(action)s resource (%(id)s) due '
                    'to: %(msg)s') % {
                        'action': action[:-1] + 'ing',
                        'id': self.physical_id,
                        'msg': msg
                    }
     else:
         # Exception happens before physical node creatin started.
         reason = _('Profile failed in creating node due to: %(msg)s') % {
             'msg': msg
         }
     self.set_status(context, self.ERROR, reason)
     self.store(context)
Example #7
0
    def test_warning(self, mock_dump):
        entity = mock.Mock(id='1234567890')
        entity.name = 'fake_obj'
        action = mock.Mock(entity=entity, action='ACTION_NAME')

        res = event.warning(action, 'P1', 'R1', 'TS1')

        self.assertIsNone(res)
        mock_dump.assert_called_once_with(logging.WARNING, action, 'P1', 'R1',
                                          'TS1')
Example #8
0
    def _wait_for_lb_ready(self, lb_id, timeout=60, ignore_not_found=False):
        """Keep waiting until loadbalancer is ready

        This method will keep waiting until loadbalancer resource specified
        by lb_id becomes ready, i.e. its provisioning_status is ACTIVE and
        its operating_status is ONLINE.

        :param lb_id: ID of the load-balancer to check.
        :param timeout: timeout in seconds.
        :param ignore_not_found: if set to True, nonexistent loadbalancer
            resource is also an acceptable result.
        """
        waited = 0
        while waited < timeout:
            try:
                lb = self.nc().loadbalancer_get(lb_id)
            except exception.InternalError as ex:
                msg = _LE('Failed in getting loadbalancer: %s.'
                          ) % six.text_type(ex)
                LOG.exception(msg)
                EVENT.warning(oslo_context.get_current(), self, 'LB_GET',
                              'ERROR', msg)
                return False
            if lb is None:
                lb_ready = ignore_not_found
            else:
                lb_ready = ((lb.provisioning_status == 'ACTIVE') and
                            (lb.operating_status == 'ONLINE'))

            if lb_ready is True:
                return True

            LOG.debug(_('Waiting for loadbalancer %(lb)s to become ready'),
                      {'lb': lb_id})

            eventlet.sleep(2)
            waited += 2

        return False
Example #9
0
    def set_status(self, result, reason=None):
        """Set action status based on return value from execute."""

        timestamp = wallclock()

        if result == self.RES_OK:
            status = self.SUCCEEDED
            ao.Action.mark_succeeded(self.context, self.id, timestamp)

        elif result == self.RES_ERROR:
            status = self.FAILED
            ao.Action.mark_failed(self.context, self.id, timestamp,
                                  reason or 'ERROR')

        elif result == self.RES_TIMEOUT:
            status = self.FAILED
            ao.Action.mark_failed(self.context, self.id, timestamp,
                                  reason or 'TIMEOUT')

        elif result == self.RES_CANCEL:
            status = self.CANCELLED
            ao.Action.mark_cancelled(self.context, self.id, timestamp)

        else:  # result == self.RES_RETRY:
            status = self.READY
            # Action failed at the moment, but can be retried
            # We abandon it and then notify other dispatchers to execute it
            ao.Action.abandon(self.context, self.id)
            dispatcher.start_action()

        if status == self.SUCCEEDED:
            EVENT.info(self, consts.PHASE_END, reason or 'SUCCEEDED')
        elif status == self.READY:
            EVENT.warning(self, consts.PHASE_ERROR, reason or 'RETRY')
        else:
            EVENT.error(self, consts.PHASE_ERROR, reason or 'ERROR')

        self.status = status
        self.status_reason = reason
Example #10
0
    def set_status(self, result, reason=None):
        """Set action status based on return value from execute."""

        timestamp = wallclock()

        if result == self.RES_OK:
            status = self.SUCCEEDED
            db_api.action_mark_succeeded(self.context, self.id, timestamp)

        elif result == self.RES_ERROR:
            status = self.FAILED
            db_api.action_mark_failed(self.context, self.id, timestamp,
                                      reason=reason or 'ERROR')

        elif result == self.RES_TIMEOUT:
            status = self.FAILED
            db_api.action_mark_failed(self.context, self.id, timestamp,
                                      reason=reason or 'TIMEOUT')

        elif result == self.RES_CANCEL:
            status = self.CANCELLED
            db_api.action_mark_cancelled(self.context, self.id, timestamp)

        else:  # result == self.RES_RETRY:
            status = self.READY
            # Action failed at the moment, but can be retried
            # We abandon it and then notify other dispatchers to execute it
            db_api.action_abandon(self.context, self.id)

        if status == self.SUCCEEDED:
            EVENT.info(self.context, self, self.action, status, reason)
        elif status == self.READY:
            EVENT.warning(self.context, self, self.action, status, reason)
        else:
            EVENT.error(self.context, self, self.action, status, reason)

        self.status = status
        self.status_reason = reason
Example #11
0
    def member_remove(self, lb_id, pool_id, member_id):
        """Delete a member from Neutron lbaas pool.

        :param lb_id: The ID of the loadbalancer the operation is targeted at;
        :param pool_id: The ID of the pool from which the member is deleted;
        :param member_id: The ID of the LB member.
        :returns: True if the operation succeeded or False if errors occurred.
        """
        try:
            self.nc().pool_member_delete(pool_id, member_id)
        except exception.InternalError as ex:
            msg = _LE('Failed in removing member %(m)s from pool %(p)s: '
                      '%(ex)s') % {'m': member_id, 'p': pool_id,
                                   'ex': six.text_type(ex)}
            LOG.exception(msg)
            EVENT.warning(oslo_context.get_current(), self,
                          'POOL_MEMBER_DELETE', 'ERROR', msg)
            return None
        res = self._wait_for_lb_ready(lb_id)
        if res is False:
            LOG.error(_LE('Failed in deleting pool member (%s).') % member_id)
            return None

        return True
Example #12
0
    def lb_create(self, vip, pool):
        """Create a LBaaS instance

        :param vip: A dict containing the properties for the VIP;
        :param pool: A dict describing the pool of load-balancer members.
        """
        def _cleanup(msg, **kwargs):
            LOG.error(msg)
            self.lb_delete(**kwargs)
            return

        result = {}
        # Create loadblancer
        try:
            subnet = self.nc().subnet_get(vip['subnet'])
        except exception.InternalError as ex:
            msg = _LE('Failed in getting subnet: %s.') % six.text_type(ex)
            LOG.exception(msg)
            EVENT.warning(oslo_context.get_current(), self, 'SUBNET_GET',
                          'ERROR', msg)
            return False, msg
        subnet_id = subnet.id
        try:
            lb = self.nc().loadbalancer_create(subnet_id,
                                               vip.get('address', None),
                                               vip['admin_state_up'])
        except exception.InternalError as ex:
            msg = _LE('Failed in creating loadbalancer: %s.'
                      ) % six.text_type(ex)
            LOG.exception(msg)
            EVENT.warning(oslo_context.get_current(), self, 'LB_CREATE',
                          'ERROR', msg)
            return False, msg
        result['loadbalancer'] = lb.id

        res = self._wait_for_lb_ready(lb.id)
        if res is False:
            msg = _LE('Failed in creating load balancer (%s).') % lb.id
            _cleanup(msg, **result)
            return False, msg

        # Create listener
        try:
            listener = self.nc().listener_create(lb.id, vip['protocol'],
                                                 vip['protocol_port'],
                                                 vip.get('connection_limit',
                                                         None),
                                                 vip['admin_state_up'])
        except exception.InternalError as ex:
            msg = _LE('Failed in creating lb listener: %s.'
                      ) % six.text_type(ex)
            LOG.exception(msg)
            EVENT.warning(oslo_context.get_current(), self, 'LISTENER_CREATE',
                          'ERROR', msg)
            return False, msg
        result['listener'] = listener.id
        res = self._wait_for_lb_ready(lb.id)
        if res is False:
            msg = _LE('Failed in creating listener (%s).') % listener.id
            _cleanup(msg, **result)
            return res, msg

        # Create pool
        try:
            pool = self.nc().pool_create(pool['lb_method'], listener.id,
                                         pool['protocol'],
                                         pool['admin_state_up'])
        except exception.InternalError as ex:
            msg = _LE('Failed in creating lb pool: %s.'
                      ) % six.text_type(ex)
            LOG.exception(msg)
            EVENT.warning(oslo_context.get_current(), self, 'POOL_CREATE',
                          'ERROR', msg)
            return False, msg
        result['pool'] = pool.id
        res = self._wait_for_lb_ready(lb.id)
        if res is False:
            msg = _LE('Failed in creating pool (%s).') % pool.id
            _cleanup(msg, **result)
            return res, msg

        return True, result
Example #13
0
    def lb_delete(self, **kwargs):
        """Delete a Neutron lbaas instance

        The following Neutron lbaas resources will be deleted in order:
        1)healthmonitor; 2)pool; 3)listener; 4)loadbalancer.
        """
        lb_id = kwargs.pop('loadbalancer')

        healthmonitor_id = kwargs.pop('healthmonitor', None)
        if healthmonitor_id:
            try:
                self.nc().healthmonitor_delete(healthmonitor_id)
            except exception.InternalError as ex:
                msg = _LE('Failed in deleting healthmonitor: %s.'
                          ) % six.text_type(ex)
                LOG.exception(msg)
                EVENT.warning(oslo_context.get_current(), self,
                              'HEALTHMONITOR_DELETE', 'ERROR', msg)
                return False, msg
            res = self._wait_for_lb_ready(lb_id)
            if res is False:
                msg = _LE('Failed in deleting healthmonitor '
                          '(%s).') % healthmonitor_id
                return False, msg

        pool_id = kwargs.pop('pool', None)
        if pool_id:
            try:
                self.nc().pool_delete(pool_id)
            except exception.InternalError as ex:
                msg = _LE('Failed in deleting lb pool: %s.'
                          ) % six.text_type(ex)
                LOG.exception(msg)
                EVENT.warning(oslo_context.get_current(), self, 'POOL_DELETE',
                              'ERROR', msg)
                return False, msg
            res = self._wait_for_lb_ready(lb_id)
            if res is False:
                msg = _LE('Failed in deleting pool (%s).') % pool_id
                return False, msg

        listener_id = kwargs.pop('listener', None)
        if listener_id:
            try:
                self.nc().listener_delete(listener_id)
            except exception.InternalError as ex:
                msg = _LE('Failed in deleting listener: %s.'
                          ) % six.text_type(ex)
                LOG.exception(msg)
                EVENT.warning(oslo_context.get_current(), self,
                              'LISTENER_DELETE', 'ERROR', msg)
                return False, msg
            res = self._wait_for_lb_ready(lb_id)
            if res is False:
                msg = _LE('Failed in deleting listener (%s).') % listener_id
                return False, msg

        self.nc().loadbalancer_delete(lb_id)
        res = self._wait_for_lb_ready(lb_id, ignore_not_found=True)
        if res is False:
            msg = _LE('Failed in deleting loadbalancer (%s).') % lb_id
            return False, msg

        return True, _('LB deletion succeeded')