Ejemplo n.º 1
0
 def test_remove_nodes_from_clb_predicate(self):
     """
     :obj:`RemoveNodesFromCLB` only succeeds on 202.
     """
     lb_id = "12345"
     node_ids = [str(i) for i in range(5)]
     step = RemoveNodesFromCLB(lb_id=lb_id, node_ids=pset(node_ids))
     request = step.as_effect()
     self.assertTrue(request.intent.json_response)
     predicate = request.intent.success_pred
     self.assertTrue(predicate(StubResponse(202, {}), None))
     self.assertFalse(predicate(StubResponse(200, {}), None))
Ejemplo n.º 2
0
 def setUp(self):
     """
     Set up :class:`RCv3Tests`.
     """
     self.reactor = object()
     self.patch(_rcv3, "perform", self._fake_perform)
     self.dispatcher = object()
     self.request_bag = _RequestBag(dispatcher=self.dispatcher,
                                    tenant_id='thetenantid')
     self.post_result = (StubResponse(201, {}),
                         _rcv3_add_response_body("lb_id", "server_id"))
     self.del_result = StubResponse(204, {}), None
Ejemplo n.º 3
0
    def test_try_again(self):
        """
        If a node was already removed (or maybe was never part of the load
        balancer pool to begin with), or some load balancer was
        inactive, or one of the load balancers doesn't exist, returns
        an effect that removes the remaining load balancer pairs.
        """
        # This little piggy isn't even on this load balancer.
        node_a_id = '825b8c72-9951-4aff-9cd8-fa3ca5551c90'
        lb_a_id = '2b0e17b6-0429-4056-b86c-e670ad5de853'

        # This little piggy is going to be removed from this load balancer.
        node_b_id = "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2"
        lb_b_id = 'd95ae0c4-6ab8-4873-b82f-f8433840cff2'

        # This little piggy isn't active!
        node_c_id = '08944038-80ba-4ae1-a188-c827444e02e2'
        lb_c_id = '150895a5-1aa7-45b7-b7a4-98b9c282f800'

        # This isn't even a little piggy!
        node_d_id = 'bc1e94c3-0c88-4828-9e93-d42259280987'
        lb_d_id = 'de52879e-1f84-4ecd-8988-91dfdc99570d'

        seq = [
            (service_request(
                service_type=ServiceType.RACKCONNECT_V3,
                method="DELETE",
                url='load_balancer_pools/nodes',
                data=[
                    {'load_balancer_pool': {'id': lb_b_id},
                     'cloud_server': {'id': node_b_id}}],
                success_pred=has_code(204, 409)).intent,
             lambda _: (StubResponse(204, {}), None)),
        ]

        body = {"errors":
                ["Node {node_id} is not a member of Load Balancer "
                 "Pool {lb_id}".format(node_id=node_a_id, lb_id=lb_a_id),
                 "Load Balancer Pool {lb_id} is not in an ACTIVE state"
                 .format(lb_id=lb_c_id),
                 "Load Balancer Pool {lb_id} does not exist"
                 .format(lb_id=lb_d_id)]}

        eff = _rcv3_check_bulk_delete(
            [(lb_a_id, node_a_id),
             (lb_b_id, node_b_id),
             (lb_c_id, node_c_id),
             (lb_d_id, node_d_id)],
            (StubResponse(409, {}), body))

        self.assertEqual(perform_sequence(seq, eff), (StepResult.SUCCESS, []))
Ejemplo n.º 4
0
 def test_log_none_effectful_fields(self):
     """
     When log is not passed, but there are log fields from BoundFields,
     the log passed to treq has those fields.
     """
     log = mock_log()
     # we have to include system='otter' in the expected log here because
     # the code falls back to otter.log.log, which has the system key bound.
     expected_log = matches(IsBoundWith(bound='stuff', system='otter'))
     req = ('GET', 'http://google.com/', None, None, None, {
         'log': expected_log
     })
     response = StubResponse(200, {})
     treq = StubTreq(reqs=[(req, response)],
                     contents=[(response, "content")])
     req = Request(method="get", url="http://google.com/")
     req.treq = treq
     req_eff = Effect(req)
     bound_log_eff = with_log(req_eff, bound='stuff')
     dispatcher = ComposedDispatcher(
         [get_simple_dispatcher(None),
          get_log_dispatcher(log, {})])
     self.assertEqual(
         self.successResultOf(perform(dispatcher, bound_log_eff)),
         (response, "content"))
Ejemplo n.º 5
0
    def test_set_metadata_item(self):
        """
        :obj:`SetMetadataItemOnServer.as_effect` produces a request for
        setting a metadata item on a particular server.  It succeeds if
        successful, but does not fail for any errors.
        """
        server_id = u'abc123'
        meta = SetMetadataItemOnServer(server_id=server_id, key='metadata_key',
                                       value='teapot')
        eff = meta.as_effect()
        seq = [
            (eff.intent, lambda i: (StubResponse(202, {}), {})),
            (Log(ANY, ANY), lambda _: None)
        ]
        self.assertEqual(
            perform_sequence(seq, eff),
            (StepResult.SUCCESS, []))

        exceptions = (NoSuchServerError("msg", server_id=server_id),
                      ServerMetadataOverLimitError("msg", server_id=server_id),
                      NovaRateLimitError("msg"),
                      APIError(code=500, body="", headers={}))
        for exception in exceptions:
            self.assertRaises(
                type(exception),
                perform_sequence,
                [(eff.intent, lambda i: raise_(exception))],
                eff)
Ejemplo n.º 6
0
 def test_filters_on_user_criteria(self):
     """
     Considers user provided filter if provided
     """
     as_servers = ([{
         'metadata': {
             'rax:auto_scaling_group_id': 'a'
         },
         'id': i
     } for i in range(5)] + [{
         'metadata': {
             'rax:auto_scaling_group_id': 'b'
         },
         'id': i
     } for i in range(5, 8)])
     servers = as_servers + [{'metadata': 'junk'}] * 3
     eff = get_all_scaling_group_servers(
         server_predicate=lambda s: s['id'] % 3 == 0)
     body = {'servers': servers}
     sequence = [(service_request(*self.req).intent, lambda i:
                  (StubResponse(200, None), body)),
                 (Log(mock.ANY, mock.ANY), lambda i: None)]
     result = perform_sequence(sequence, eff)
     self.assertEqual(result, {
         'a': [as_servers[0], as_servers[3]],
         'b': [as_servers[6]]
     })
Ejemplo n.º 7
0
 def test_returns_as_servers(self):
     """
     Returns servers with AS metadata in it grouped by scaling group ID
     """
     as_servers = ([{
         'metadata': {
             'rax:auto_scaling_group_id': 'a'
         },
         'id': i
     } for i in range(5)] + [{
         'metadata': {
             'rax:auto_scaling_group_id': 'b'
         },
         'id': i
     } for i in range(5, 8)] + [{
         'metadata': {
             'rax:auto_scaling_group_id': 'a'
         },
         'id': 10
     }])
     servers = as_servers + [{'metadata': 'junk'}] * 3
     eff = get_all_scaling_group_servers()
     body = {'servers': servers}
     sequence = [(service_request(*self.req).intent, lambda i:
                  (StubResponse(200, None), body)),
                 (Log(mock.ANY, mock.ANY), lambda i: None)]
     result = perform_sequence(sequence, eff)
     self.assertEqual(result, {
         'a': as_servers[:5] + [as_servers[-1]],
         'b': as_servers[5:8]
     })
Ejemplo n.º 8
0
    def test_good_response(self):
        """
        If the response code indicates success, the step returns a RETRY so
        that another convergence cycle can be done to update the active server
        list.
        """
        node_a_id = '825b8c72-9951-4aff-9cd8-fa3ca5551c90'
        lb_a_id = '2b0e17b6-0429-4056-b86c-e670ad5de853'

        node_b_id = "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2"
        lb_b_id = 'd95ae0c4-6ab8-4873-b82f-f8433840cff2'

        pairs = [(lb_a_id, node_a_id), (lb_b_id, node_b_id)]

        resp = StubResponse(201, {})
        body = [{"cloud_server": {"id": node_id},
                 "load_balancer_pool": {"id": lb_id}}
                for (lb_id, node_id) in pairs]
        res = _rcv3_check_bulk_add(pairs, (resp, body))
        self.assertEqual(
            res,
            (StepResult.RETRY,
             [ErrorReason.String(
              'must re-gather after adding to LB in order to update the '
              'active cache')]))
Ejemplo n.º 9
0
 def test_ensure_retry(self):
     """Tests that retry will be returned."""
     seq = [
         (self.check_call.intent, lambda _: (StubResponse(204, ''), None)),
         (Log('request-check-stack', ANY), lambda _: None)
     ]
     reason = 'Waiting for stack check to complete'
     result = perform_sequence(seq, CheckStack(self.stack).as_effect())
     self.assertEqual(result,
                      (StepResult.RETRY, [ErrorReason.String(reason)]))
Ejemplo n.º 10
0
 def test_retry_false(self):
     """Tests correct behavior when retry is passed as false."""
     seq = [
         (self.update_call.intent, lambda _: (StubResponse(202, ''), None)),
         (Log('request-update-stack', ANY), lambda _: None)
     ]
     update = UpdateStack(stack=self.stack, stack_config=self.config,
                          retry=False)
     result = perform_sequence(seq, update.as_effect())
     self.assertEqual(result, (StepResult.SUCCESS, []))
Ejemplo n.º 11
0
 def test_delete_and_verify_verify_404(self):
     """
     :func:`delete_and_verify` gets server details after successful delete
     and succeeds if get server details returns 404
     """
     eff = delete_and_verify('sid')
     eff = resolve_effect(
         eff, service_request_error_response(APIError(204, {})),
         is_error=True)
     r = resolve_effect(eff, (StubResponse(404, {}), {"itemNotFound": {}}))
     self.assertIsNone(r)
Ejemplo n.º 12
0
 def test_retry_default(self):
     """Tests correct behavior when retry is not specified."""
     seq = [
         (self.update_call.intent, lambda _: (StubResponse(202, ''), None)),
         (Log('request-update-stack', ANY), lambda _: None)
     ]
     update = UpdateStack(stack=self.stack, stack_config=self.config)
     reason = 'Waiting for stack to update'
     result = perform_sequence(seq, update.as_effect())
     self.assertEqual(result,
                      (StepResult.RETRY, [ErrorReason.String(reason)]))
Ejemplo n.º 13
0
 def test_filters_no_metadata(self):
     """
     Servers without metadata are not included in the result.
     """
     servers = [{'id': i} for i in range(10)]
     eff = get_all_scaling_group_servers()
     body = {'servers': servers}
     sequence = [(service_request(*self.req).intent, lambda i:
                  (StubResponse(200, None), body)),
                 (Log(mock.ANY, mock.ANY), lambda i: None)]
     result = perform_sequence(sequence, eff)
     self.assertEqual(result, {})
Ejemplo n.º 14
0
    def test_try_again(self):
        """
        If a node is already on the load balancer, returns an effect that
        removes the remaining load balancer pairs.
        """
        # This little piggy is already on the load balancer
        node_a_id = '825b8c72-9951-4aff-9cd8-fa3ca5551c90'
        lb_a_id = '2b0e17b6-0429-4056-b86c-e670ad5de853'

        # This little piggy is going to be added to this load balancer
        node_b_id = "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2"
        lb_b_id = 'd95ae0c4-6ab8-4873-b82f-f8433840cff2'

        seq = [
            (service_request(
                service_type=ServiceType.RACKCONNECT_V3,
                method="POST",
                url='load_balancer_pools/nodes',
                data=[
                    {'load_balancer_pool': {'id': lb_b_id},
                     'cloud_server': {'id': node_b_id}}],
                success_pred=has_code(201, 409)).intent,
             lambda _: (StubResponse(201, {}), None)),
        ]

        body = {"errors":
                ["Cloud Server {node_id} is already a member of Load "
                 "Balancer Pool {lb_id}"
                 .format(node_id=node_a_id, lb_id=lb_a_id)]}

        eff = _rcv3_check_bulk_add(
            [(lb_a_id, node_a_id),
             (lb_b_id, node_b_id)],
            (StubResponse(409, {}), body))

        self.assertEqual(
            perform_sequence(seq, eff),
            (StepResult.RETRY,
             [ErrorReason.String(reason="must re-gather after adding to LB in "
                                        "order to update the active cache")]))
Ejemplo n.º 15
0
 def test_change_load_balancer_node(self):
     """
     :obj:`ChangeCLBNode.as_effect` produces a request for
     modifying a load balancer node.
     """
     eff = self._change_node_eff()
     retry_result = (
         StepResult.RETRY,
         [ErrorReason.String(
             'must re-gather after CLB change in order to update the '
             'active cache')])
     seq = [(eff.intent, lambda i: (StubResponse(202, {}), {}))]
     self.assertEqual(perform_sequence(seq, eff), retry_result)
Ejemplo n.º 16
0
 def test_ensure_retry(self):
     """Tests that retry will be returned."""
     seq = [
         (delete_stack(stack_id='foo', stack_name='bar').intent,
          lambda _: (StubResponse(204, ''), None)),
         (Log('request-delete-stack', ANY), lambda _: None)
     ]
     foo_stack = stack(id='foo', name='bar')
     delete = DeleteStack(foo_stack)
     reason = ('Waiting for stack to delete')
     result = perform_sequence(seq, delete.as_effect())
     self.assertEqual(result,
                      (StepResult.RETRY, [ErrorReason.String(reason)]))
Ejemplo n.º 17
0
 def test_filters_no_as_metadata(self):
     """
     Does not include servers which have metadata but does not have AS info
     in it
     """
     servers = [{'id': i, 'metadata': {}} for i in range(10)]
     eff = get_all_scaling_group_servers()
     body = {'servers': servers}
     sequence = [(service_request(*self.req).intent, lambda i:
                  (StubResponse(200, None), body)),
                 (Log(mock.ANY, mock.ANY), lambda i: None)]
     result = perform_sequence(sequence, eff)
     self.assertEqual(result, {})
Ejemplo n.º 18
0
    def test_inactive_lb(self):
        """
        If the load balancer pool is inactive, the response was successful.
        """
        node_id = '825b8c72-9951-4aff-9cd8-fa3ca5551c90'
        inactive_lb_id = '2b0e17b6-0429-4056-b86c-e670ad5de853'
        pairs = [(inactive_lb_id, node_id)]

        resp = StubResponse(409, {})
        body = {"errors": ["Load Balancer Pool {} is not in an ACTIVE state"
                           .format(inactive_lb_id)]}
        result = _rcv3_check_bulk_delete(pairs, (resp, body))
        self.assertEqual(result, (StepResult.SUCCESS, []))
Ejemplo n.º 19
0
    def test_with_changes_since(self):
        """
        If given, servers are fetched based on changes_since
        """
        since = datetime(2010, 10, 10, 10, 10, 0)
        eff = get_all_scaling_group_servers(changes_since=since)
        body = {'servers': []}

        sequence = [(service_request(
            **svc_request_args(changes_since=since, limit=100)).intent,
                     lambda i: (StubResponse(200, None), body)),
                    (Log(mock.ANY, mock.ANY), lambda i: None)]
        result = perform_sequence(sequence, eff)
        self.assertEqual(result, {})
Ejemplo n.º 20
0
    def test_lb_does_not_exist(self):
        """
        If the load balancer doesn't even exist, the delete was successful.
        """
        node_id = '825b8c72-9951-4aff-9cd8-fa3ca5551c90'
        nonexistent_lb_id = '2b0e17b6-0429-4056-b86c-e670ad5de853'

        pairs = [(nonexistent_lb_id, node_id)]

        resp = StubResponse(409, {})
        body = {"errors": ["Load Balancer Pool {} does not exist"
                           .format(nonexistent_lb_id)]}
        result = _rcv3_check_bulk_delete(pairs, (resp, body))
        self.assertEqual(result, (StepResult.SUCCESS, []))
Ejemplo n.º 21
0
    def test_set_nova_metadata_item_success(self):
        """
        Produce a request setting a metadata item on a Nova server, which
        returns a successful result on 200.
        """
        server_id, expected, real = self._setup_for_set_nova_metadata_item()
        body = {"meta": {"k": "v"}}

        seq = [(expected.intent,
                service_request_eqf(stub_pure_response(json.dumps(body),
                                                       200))),
               (log_intent('request-set-metadata-item', body), lambda _: None)]
        resp, response_json = perform_sequence(seq, real)
        self.assertEqual(resp, StubResponse(200, {}))
        self.assertEqual(response_json, body)
Ejemplo n.º 22
0
 def test_get_server_details_success(self):
     """
     Produce a request getting a Nova server's details, which
     returns a successful result on 200.
     """
     server_id, expected, real = self._setup_for_get_server_details()
     body = {"so much": "data"}
     seq = [(expected.intent,
             service_request_eqf(stub_pure_response(json.dumps(body),
                                                    200))),
            (log_intent('request-one-server-details',
                        body), lambda _: None)]
     resp, response_json = perform_sequence(seq, real)
     self.assertEqual(resp, StubResponse(200, {}))
     self.assertEqual(response_json, body)
Ejemplo n.º 23
0
    def test_node_already_a_member(self):
        """
        If all nodes were already member of the load balancers we were
        trying to add them to, the request is successful.
        """
        node_id = "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2"
        lb_id = 'd95ae0c4-6ab8-4873-b82f-f8433840cff2'
        pairs = [(lb_id, node_id)]

        resp = StubResponse(409, {})
        body = {"errors": [
            "Cloud Server {node_id} is already a member of Load "
            "Balancer Pool {lb_id}".format(node_id=node_id, lb_id=lb_id)]}
        result = _rcv3_check_bulk_add(pairs, (resp, body))
        self.assertEqual(result, (StepResult.SUCCESS, []))
Ejemplo n.º 24
0
    def test_node_not_a_member(self):
        """
        If the nodes are already not member of the load balancer pools
        they're being removed from, the response was successful.
        """
        node_id = '825b8c72-9951-4aff-9cd8-fa3ca5551c90'
        lb_id = '2b0e17b6-0429-4056-b86c-e670ad5de853'
        pairs = [(lb_id, node_id)]

        resp = StubResponse(409, {})
        body = {"errors": [
            "Node {node_id} is not a member of Load Balancer "
            "Pool {lb_id}".format(node_id=node_id, lb_id=lb_id)]}
        result = _rcv3_check_bulk_delete(pairs, (resp, body))
        self.assertEqual(result, (StepResult.SUCCESS, []))
Ejemplo n.º 25
0
 def test_log(self):
     """
     The log specified in the Request is passed on to the treq
     implementation.
     """
     log = object()
     req = ('GET', 'http://google.com/', None, None, None, {'log': log})
     response = StubResponse(200, {})
     treq = StubTreq(reqs=[(req, response)],
                     contents=[(response, "content")])
     req = Request(method="get", url="http://google.com/", log=log)
     req.treq = treq
     dispatcher = get_simple_dispatcher(None)
     self.assertEqual(
         self.successResultOf(perform(dispatcher, Effect(req))),
         (response, "content"))
Ejemplo n.º 26
0
    def test_add_nodes_to_clb_success_response_codes(self):
        """
        :obj:`AddNodesToCLB` succeeds on 202.
        """
        eff = self._add_one_node_to_clb()
        seq = SequenceDispatcher([
            (eff.intent, lambda i: (StubResponse(202, {}), '')),
            (Log(ANY, ANY), lambda _: None)
        ])
        expected = (
            StepResult.RETRY,
            [ErrorReason.String('must re-gather after adding to CLB in order '
                                'to update the active cache')])

        with seq.consume():
            self.assertEquals(sync_perform(seq, eff), expected)
Ejemplo n.º 27
0
 def test_delete_and_verify_verify_unexpectedstatus(self):
     """
     :func:`delete_and_verify` raises `UnexpectedServerStatus` error
     if server status returned after deleting is not "deleting"
     """
     eff = delete_and_verify('sid')
     eff = resolve_effect(
         eff, service_request_error_response(APIError(204, {})),
         is_error=True)
     self.assertRaises(
         UnexpectedServerStatus,
         resolve_effect,
         eff,
         (StubResponse(200, {}),
          {'server': {"OS-EXT-STS:task_state": 'bad'}})
     )
Ejemplo n.º 28
0
 def test_perform(self):
     """
     The Request effect dispatches a request to treq, and returns a
     two-tuple of the Twisted Response object and the content as bytes.
     """
     req = ('GET', 'http://google.com/', None, None, None, {
         'log': default_log
     })
     response = StubResponse(200, {})
     treq = StubTreq(reqs=[(req, response)],
                     contents=[(response, "content")])
     req = Request(method="get", url="http://google.com/")
     req.treq = treq
     dispatcher = get_simple_dispatcher(None)
     self.assertEqual(
         self.successResultOf(perform(dispatcher, Effect(req))),
         (response, "content"))
Ejemplo n.º 29
0
    def test_lb_does_not_exist(self):
        """
        If one of the LBs we tried to attach one or more nodes to does not
        exist, the request fails.
        """
        node_id = "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2"
        lb_id = 'd95ae0c4-6ab8-4873-b82f-f8433840cff2'
        pairs = [(lb_id, node_id)]

        resp = StubResponse(409, {})
        body = {"errors": [
            "Load Balancer Pool {lb_id} does not exist"
            .format(lb_id=lb_id)]}
        result = _rcv3_check_bulk_add(pairs, (resp, body))
        self.assertEqual(
            result,
            (StepResult.FAILURE,
             ["RCv3 LB {lb_id} does not exist".format(lb_id=lb_id)]))
Ejemplo n.º 30
0
    def test_normal_use(self):
        """Tests normal usage."""

        stack_config = pmap({'stack_name': 'baz', 'foo': 'bar'})
        new_stack_config = pmap({'stack_name': 'baz_foo', 'foo': 'bar'})

        self.create = CreateStack(stack_config)
        self.seq = [
            (Func(uuid4), lambda _: 'foo'),
            (create_stack(thaw(new_stack_config)).intent,
             lambda _: (StubResponse(200, {}), {'stack': {}})),
            (Log('request-create-stack', ANY), lambda _: None)
        ]

        reason = 'Waiting for stack to create'
        result = perform_sequence(self.seq, self.create.as_effect())
        self.assertEqual(result,
                         (StepResult.RETRY, [ErrorReason.String(reason)]))