Beispiel #1
0
    def as_effect(self):
        """Produce a :obj:`Effect` to set a metadata item on a server"""
        eff = set_nova_metadata_item(server_id=self.server_id,
                                     key=self.key,
                                     value=self.value)

        return eff.on(success=lambda _: (StepResult.SUCCESS, []))
Beispiel #2
0
def convergence_remove_server_from_group(log, transaction_id, server_id,
                                         replace, purge, group, state):
    """
    Remove a specific server from the group, optionally decrementing the
    desired capacity.

    The server may just be scheduled for deletion, or it may be evicted from
    the group by removing otter-specific metdata from the server.

    :param log: A bound logger
    :param bytes trans_id: The transaction id for this operation.
    :param bytes server_id: The id of the server to be removed.
    :param bool replace: Should the server be replaced?
    :param bool purge: Should the server be deleted from Nova?
    :param group: The scaling group to remove a server from.
    :type group: :class:`~otter.models.interface.IScalingGroup`
    :param state: The current state of the group.
    :type state: :class:`~otter.models.interface.GroupState`

    :return: The updated state.
    :rtype: Effect of :class:`~otter.models.interface.GroupState`

    :raise: :class:`CannotDeleteServerBelowMinError` if the server cannot
        be deleted without replacement, and :class:`ServerNotFoundError` if
        there is no such server to be deleted.
    """
    effects = [_is_server_in_group(group, server_id)]
    if not replace:
        effects.append(_can_scale_down(group, server_id))

    # the (possibly) two checks can happen in parallel, but we want
    # ServerNotFoundError to take precedence over
    # CannotDeleteServerBelowMinError
    both_checks = yield parallel_all_errors(effects)
    for is_error, result in both_checks:
        if is_error:
            reraise(*result)

    # Remove the server
    if purge:
        eff = set_nova_metadata_item(server_id, *DRAINING_METADATA)
    else:
        eff = Effect(
            EvictServerFromScalingGroup(log=log,
                                        transaction_id=transaction_id,
                                        scaling_group=group,
                                        server_id=server_id))
    yield Effect(
        TenantScope(
            retry_effect(eff, retry_times(3), exponential_backoff_interval(2)),
            group.tenant_id))

    if not replace:
        yield do_return(assoc_obj(state, desired=state.desired - 1))
    else:
        yield do_return(state)
Beispiel #3
0
def convergence_remove_server_from_group(
        log, transaction_id, server_id, replace, purge, group, state):
    """
    Remove a specific server from the group, optionally decrementing the
    desired capacity.

    The server may just be scheduled for deletion, or it may be evicted from
    the group by removing otter-specific metdata from the server.

    :param log: A bound logger
    :param bytes trans_id: The transaction id for this operation.
    :param bytes server_id: The id of the server to be removed.
    :param bool replace: Should the server be replaced?
    :param bool purge: Should the server be deleted from Nova?
    :param group: The scaling group to remove a server from.
    :type group: :class:`~otter.models.interface.IScalingGroup`
    :param state: The current state of the group.
    :type state: :class:`~otter.models.interface.GroupState`

    :return: The updated state.
    :rtype: Effect of :class:`~otter.models.interface.GroupState`

    :raise: :class:`CannotDeleteServerBelowMinError` if the server cannot
        be deleted without replacement, and :class:`ServerNotFoundError` if
        there is no such server to be deleted.
    """
    effects = [_is_server_in_group(group, server_id)]
    if not replace:
        effects.append(_can_scale_down(group, server_id))

    # the (possibly) two checks can happen in parallel, but we want
    # ServerNotFoundError to take precedence over
    # CannotDeleteServerBelowMinError
    both_checks = yield parallel_all_errors(effects)
    for is_error, result in both_checks:
        if is_error:
            reraise(*result)

    # Remove the server
    if purge:
        eff = set_nova_metadata_item(server_id, *DRAINING_METADATA)
    else:
        eff = Effect(
            EvictServerFromScalingGroup(log=log,
                                        transaction_id=transaction_id,
                                        scaling_group=group,
                                        server_id=server_id))
    yield Effect(TenantScope(
        retry_effect(eff, retry_times(3), exponential_backoff_interval(2)),
        group.tenant_id))

    if not replace:
        yield do_return(assoc_obj(state, desired=state.desired - 1))
    else:
        yield do_return(state)
Beispiel #4
0
 def _setup_for_set_nova_metadata_item(self):
     """
     Produce the data needed to test :obj:`set_nova_metadata_item`: a tuple
     of (server_id, expected_effect, real_effect)
     """
     server_id = unicode(uuid4())
     real = set_nova_metadata_item(server_id=server_id, key='k', value='v')
     expected = service_request(
         ServiceType.CLOUD_SERVERS,
         'PUT',
         'servers/{0}/metadata/k'.format(server_id),
         data={'meta': {'k': 'v'}},
         reauth_codes=(401,),
         success_pred=has_code(200))
     return (server_id, expected, real)
Beispiel #5
0
 def _setup_for_set_nova_metadata_item(self):
     """
     Produce the data needed to test :obj:`set_nova_metadata_item`: a tuple
     of (server_id, expected_effect, real_effect)
     """
     server_id = unicode(uuid4())
     real = set_nova_metadata_item(server_id=server_id, key='k', value='v')
     expected = service_request(ServiceType.CLOUD_SERVERS,
                                'PUT',
                                'servers/{0}/metadata/k'.format(server_id),
                                data={'meta': {
                                    'k': 'v'
                                }},
                                reauth_codes=(401, ),
                                success_pred=has_code(200))
     return (server_id, expected, real)
Beispiel #6
0
    def as_effect(self):
        """Produce a :obj:`Effect` to set a metadata item on a server"""
        eff = set_nova_metadata_item(
            server_id=self.server_id, key=self.key, value=self.value)

        return eff.on(success=lambda _: (StepResult.SUCCESS, []))