Example #1
0
def lb_req(url, json_response, response):
    """
    Return a SequenceDispatcher two-tuple that matches a service request to a
    particular load balancer endpoint (using GET), and returns the given
    ``response`` as the content in an HTTP 200 ``StubResponse``.
    """
    if isinstance(response, Exception):
        def handler(i): raise response
        log_seq = []
    else:
        def handler(i): return (StubResponse(200, {}), response)
        log_seq = [(Log(mock.ANY, mock.ANY), lambda i: None)]
    return (
        Retry(
            effect=mock.ANY,
            should_retry=ShouldDelayAndRetry(
                can_retry=retry_times(5),
                next_interval=exponential_backoff_interval(2))
        ),
        nested_sequence([
            (service_request(
                ServiceType.CLOUD_LOAD_BALANCERS,
                'GET', url, json_response=json_response).intent,
             handler)
        ] + log_seq)
    )
Example #2
0
    def _perform_add_event(self, response_sequence):
        """
        Given a sequence of functions that take an intent and returns a
        response (or raises an exception), perform :func:`add_event` and
        return the result.
        """
        log = object()
        eff = add_event(self.event, 'tid', 'ord', log)
        uid = '00000000-0000-0000-0000-000000000000'

        svrq = service_request(
            ServiceType.CLOUD_FEEDS, 'POST', 'autoscale/events',
            headers={
                'content-type': ['application/vnd.rackspace.atom+json']},
            data=self._get_request('INFO', uid, 'tid'), log=log,
            success_pred=has_code(201),
            json_response=False)

        seq = [
            (TenantScope(mock.ANY, 'tid'), nested_sequence([
                retry_sequence(
                    Retry(effect=svrq, should_retry=ShouldDelayAndRetry(
                        can_retry=mock.ANY,
                        next_interval=exponential_backoff_interval(2))),
                    response_sequence
                )
            ]))
        ]

        return perform_sequence(seq, eff)
Example #3
0
def lb_req(url, json_response, response):
    """
    Return a SequenceDispatcher two-tuple that matches a service request to a
    particular load balancer endpoint (using GET), and returns the given
    ``response`` as the content in an HTTP 200 ``StubResponse``.
    """
    if isinstance(response, Exception):
        def handler(i): raise response
        log_seq = []
    else:
        def handler(i): return (StubResponse(200, {}), response)
        log_seq = [(Log(mock.ANY, mock.ANY), lambda i: None)]
    return (
        Retry(
            effect=mock.ANY,
            should_retry=ShouldDelayAndRetry(
                can_retry=retry_times(5),
                next_interval=exponential_backoff_interval(2))
        ),
        nested_sequence([
            (service_request(
                ServiceType.CLOUD_LOAD_BALANCERS,
                'GET', url, json_response=json_response).intent,
             handler)
        ] + log_seq)
    )
Example #4
0
def node_feed_req(lb_id, node_id, response):
    """
    Return (intent, performer) sequence for getting clb node's feed that
    wrapped with retry intent.

    :param lb_id: Lodbalancer ID
    :param node_id: LB node ID
    :param response: The response returned when getting CLB node feed. It is
        either string containing feed or Exception object that will be raised
        when getting the feed

    :return: (intent, performer) tuple
    """
    if isinstance(response, Exception):
        def handler(i): raise response
    else:
        def handler(i): return response
    return (
        Retry(
            effect=mock.ANY,
            should_retry=ShouldDelayAndRetry(
                can_retry=retry_times(5),
                next_interval=exponential_backoff_interval(2))
        ),
        nested_sequence([(("gcnf", lb_id, node_id), handler)])
    )
Example #5
0
 def dispatcher(self, operation, resp):
     return SequenceDispatcher([
         (TenantScope(mock.ANY, "tid"),
          nested_sequence([
              ((operation, pset([("lb_id", "server_id")])), lambda i: resp)
          ]))
     ])
Example #6
0
    def _perform_add_event(self, response_sequence):
        """
        Given a sequence of functions that take an intent and returns a
        response (or raises an exception), perform :func:`add_event` and
        return the result.
        """
        log = object()
        eff = add_event(self.event, 'tid', 'ord', log)
        uid = '00000000-0000-0000-0000-000000000000'

        svrq = service_request(
            ServiceType.CLOUD_FEEDS,
            'POST',
            'autoscale/events',
            headers={'content-type': ['application/vnd.rackspace.atom+json']},
            data=self._get_request('INFO', uid, 'tid'),
            log=log,
            success_pred=has_code(201),
            json_response=False)

        seq = [
            (TenantScope(mock.ANY, 'tid'),
             nested_sequence([
                 retry_sequence(
                     Retry(effect=svrq,
                           should_retry=ShouldDelayAndRetry(
                               can_retry=mock.ANY,
                               next_interval=exponential_backoff_interval(2))),
                     response_sequence)
             ]))
        ]

        return perform_sequence(seq, eff)
Example #7
0
    def test_throttling(self):
        """
        When the throttler function returns a bracketing function, it's used to
        throttle the request.
        """
        def throttler(stype, method, tid):
            if (stype == ServiceType.CLOUD_SERVERS and
                    method == 'get' and tid == 1):
                return bracket
        bracket = object()
        svcreq = service_request(
            ServiceType.CLOUD_SERVERS, 'GET', 'servers').intent

        response = stub_pure_response({}, 200)
        seq = SequenceDispatcher([
            (_Throttle(bracket=bracket, effect=mock.ANY),
             nested_sequence([
                 (Authenticate(authenticator=self.authenticator,
                               tenant_id=1,
                               log=self.log),
                  lambda i: ('token', fake_service_catalog)),
                 (Request(method='GET', url='http://dfw.openstack/servers',
                          headers=headers('token'), log=self.log),
                  lambda i: response),
             ])),
        ])

        eff = self._concrete(svcreq, throttler=throttler)
        with seq.consume():
            result = sync_perform(seq, eff)
        self.assertEqual(result, (response[0], {}))
Example #8
0
    def test_ignore_disappearing_divergent_flag(self):
        """
        When the divergent flag disappears just as we're starting to converge,
        the group does not get converged and None is returned as its result.

        This happens when a concurrent convergence iteration is just finishing
        up.
        """
        eff = self._converge_all_groups(['00_g1'])

        def get_bound_sequence(tid, gid):
            # since this GetStat is going to return None, no more effects will
            # be run. This is the crux of what we're testing.
            znode = '/groups/divergent/{}_{}'.format(tid, gid)
            return [
                (GetStat(path=znode), noop),
                (Log('converge-divergent-flag-disappeared',
                     fields={'znode': znode}),
                 noop)]

        sequence = [
            (ReadReference(ref=self.currently_converging), lambda i: pset()),
            (Log('converge-all-groups',
                 dict(group_infos=[self.group_infos[0]],
                      currently_converging=[])),
             noop),
            (ReadReference(ref=self.recently_converged), lambda i: pmap()),
            (Func(time.time), lambda i: 100),
            parallel_sequence([
                [(BoundFields(mock.ANY, fields={'tenant_id': '00',
                                                'scaling_group_id': 'g1'}),
                  nested_sequence(get_bound_sequence('00', 'g1')))],
             ]),
        ]
        self.assertEqual(perform_sequence(sequence, eff), [None])
Example #9
0
    def test_throttling(self):
        """
        When the throttler function returns a bracketing function, it's used to
        throttle the request.
        """
        def throttler(stype, method, tid):
            if (stype == ServiceType.CLOUD_SERVERS and method == 'get'
                    and tid == 1):
                return bracket

        bracket = object()
        svcreq = service_request(ServiceType.CLOUD_SERVERS, 'GET',
                                 'servers').intent

        response = stub_pure_response({}, 200)
        seq = SequenceDispatcher([
            (_Throttle(bracket=bracket, effect=mock.ANY),
             nested_sequence([
                 (Authenticate(authenticator=self.authenticator,
                               tenant_id=1,
                               log=self.log), lambda i:
                  ('token', fake_service_catalog)),
                 (Request(method='GET',
                          url='http://dfw.openstack/servers',
                          headers=headers('token'),
                          log=self.log), lambda i: response),
             ])),
        ])

        eff = self._concrete(svcreq, throttler=throttler)
        with seq.consume():
            result = sync_perform(seq, eff)
        self.assertEqual(result, (response[0], {}))
Example #10
0
 def _expect_group_converged(self, tenant_id, group_id):
     """
     Return a SequenceDispatcher two-tuple that matches the usual sequence
     of intents for converging a single group.
     """
     return (
         BoundFields(mock.ANY,
                     dict(tenant_id=tenant_id, scaling_group_id=group_id)),
         nested_sequence([
             (GetStat(
                 path='/groups/divergent/{tenant_id}_{group_id}'.format(
                     tenant_id=tenant_id, group_id=group_id)),
              lambda i: ZNodeStatStub(version=5)),
             (TenantScope(mock.ANY, tenant_id),
              nested_sequence([
                  (('converge', tenant_id, group_id, 5, 3600),
                   lambda i: 'converged {}!'.format(group_id)),
              ])),
         ]))
Example #11
0
 def _log_sequence(self, intents):
     uid = uuid.uuid4()
     exp_uid = str(uid)
     return SequenceDispatcher([
         (Func(uuid.uuid4), lambda i: uid),
         (BoundFields(effect=mock.ANY,
                      fields={'otter_service': 'converger',
                              'converger_run_id': exp_uid}),
          nested_sequence(intents)),
     ])
Example #12
0
 def test_active_resumed(self):
     """
     Convergence is triggerred on ACTIVE resumed group
     """
     seq = [
         (GetScalingGroupInfo(tenant_id="tid", group_id="gid"),
          const(("group", self.manifest))),
         (BoundFields(effect=mock.ANY,
                      fields=dict(tenant_id="tid", scaling_group_id="gid")),
          nested_sequence([(("tg", "tid", "gid"), noop)]))
     ]
     self.assertIsNone(
         perform_sequence(seq, sh.check_and_trigger("tid", "gid")))
Example #13
0
    def setUp(self):
        """
        mock dependent functions
        """
        self.connect_cass_servers = patch(
            self, 'otter.metrics.connect_cass_servers')
        self.client = mock.Mock(spec=['disconnect'])
        self.client.disconnect.return_value = succeed(None)
        self.connect_cass_servers.return_value = self.client

        self.log = mock_log()

        self.get_all_metrics = patch(self, 'otter.metrics.get_all_metrics',
                                     return_value=succeed("metrics"))
        self.groups = [
            {"tenantId": "t1", "groupId": "g1",
             "launch_config": '{"type": "launch_server"}'},
            {"tenantId": "t1", "groupId": "g2",
             "launch_config": '{"type": "launch_server"}'},
            {"tenantId": "t1", "groupId": "g12",
             "launch_config": '{"type": "launch_stack"}'},
            {"tenantId": "t3", "groupId": "g3",
             "launch_config": '{"type": "launch_stack"}'},
            {"tenantId": "t2", "groupId": "g11",
             "launch_config": '{"type": "launch_server"}'}]
        self.lc_groups = {"t1": self.groups[:2], "t2": [self.groups[-1]]}

        self.add_to_cloud_metrics = patch(
            self, 'otter.metrics.add_to_cloud_metrics',
            side_effect=intent_func("atcm"))

        self.config = {'cassandra': 'c', 'identity': identity_config,
                       'metrics': {'service': 'ms', 'tenant_id': 'tid',
                                   'region': 'IAD',
                                   'ttl': 200, "last_tenant_fpath": "lpath"},
                       'region': 'r', 'cloudServersOpenStack': 'nova',
                       'cloudLoadBalancers': 'clb',
                       'cloudOrchestration': 'orch',
                       'rackconnect': 'rc',
                       "non-convergence-tenants": ["ct"]}

        self.sequence = SequenceDispatcher([
            (GetAllValidGroups(), const(self.groups)),
            (TenantScope(mock.ANY, "tid"),
             nested_sequence([
                 (("atcm", 200, "r", "metrics", 2, self.config,
                   self.log, False), noop)
             ]))
        ])
        self.get_dispatcher = patch(self, "otter.metrics.get_dispatcher",
                                    return_value=self.sequence)
Example #14
0
    def setUp(self):
        """
        mock dependent functions
        """
        self.connect_cass_servers = patch(self, "otter.metrics.connect_cass_servers")
        self.client = mock.Mock(spec=["disconnect"])
        self.client.disconnect.return_value = succeed(None)
        self.connect_cass_servers.return_value = self.client

        self.log = mock_log()

        self.get_all_metrics = patch(self, "otter.metrics.get_all_metrics", return_value=succeed("metrics"))
        self.groups = [
            {"tenantId": "t1", "groupId": "g1", "launch_config": '{"type": "launch_server"}'},
            {"tenantId": "t1", "groupId": "g2", "launch_config": '{"type": "launch_server"}'},
            {"tenantId": "t1", "groupId": "g12", "launch_config": '{"type": "launch_stack"}'},
            {"tenantId": "t3", "groupId": "g3", "launch_config": '{"type": "launch_stack"}'},
            {"tenantId": "t2", "groupId": "g11", "launch_config": '{"type": "launch_server"}'},
        ]
        self.lc_groups = {"t1": self.groups[:2], "t2": [self.groups[-1]]}

        self.add_to_cloud_metrics = patch(self, "otter.metrics.add_to_cloud_metrics", side_effect=intent_func("atcm"))

        self.config = {
            "cassandra": "c",
            "identity": identity_config,
            "metrics": {"service": "ms", "tenant_id": "tid", "region": "IAD", "ttl": 200, "last_tenant_fpath": "lpath"},
            "region": "r",
            "cloudServersOpenStack": "nova",
            "cloudLoadBalancers": "clb",
            "cloudOrchestration": "orch",
            "rackconnect": "rc",
            "non-convergence-tenants": ["ct"],
        }

        self.sequence = SequenceDispatcher(
            [
                (GetAllValidGroups(), const(self.groups)),
                (
                    TenantScope(mock.ANY, "tid"),
                    nested_sequence([(("atcm", 200, "r", "metrics", 2, self.config, self.log, False), noop)]),
                ),
            ]
        )
        self.get_dispatcher = patch(self, "otter.metrics.get_dispatcher", return_value=self.sequence)
Example #15
0
    def setUp(self):
        """
        mock dependent functions
        """
        self.connect_cass_servers = patch(
            self, 'otter.metrics.connect_cass_servers')
        self.client = mock.Mock(spec=['disconnect'])
        self.client.disconnect.return_value = succeed(None)
        self.connect_cass_servers.return_value = self.client

        self.get_todays_scaling_groups = patch(
            self, 'otter.metrics.get_todays_scaling_groups',
            side_effect=intent_func("gtsg"))
        self.log = mock_log()

        self.metrics = [GroupMetrics('t', 'g1', 3, 2, 0),
                        GroupMetrics('t2', 'g1', 4, 4, 1),
                        GroupMetrics('t2', 'g', 100, 20, 0)]
        self.get_all_metrics = patch(self, 'otter.metrics.get_all_metrics',
                                     return_value=succeed(self.metrics))
        self.groups = {"t": "t1group", "t2": "2 groups"}

        self.add_to_cloud_metrics = patch(
            self, 'otter.metrics.add_to_cloud_metrics',
            side_effect=intent_func("atcm"))

        self.config = {'cassandra': 'c', 'identity': identity_config,
                       'metrics': {'service': 'ms', 'tenant_id': 'tid',
                                   'region': 'IAD',
                                   'ttl': 200, "last_tenant_fpath": "lpath"},
                       'region': 'r', 'cloudServersOpenStack': 'nova',
                       'cloudLoadBalancers': 'clb', 'rackconnect': 'rc',
                       "convergence-tenants": ["ct"]}

        self.sequence = SequenceDispatcher([
            (("gtsg", ["ct"], "lpath"), const(self.groups)),
            (TenantScope(mock.ANY, "tid"),
             nested_sequence([
                 (("atcm", 200, "r", 107, 26, 1, 2, 3, self.log), noop)
             ]))
        ])
        self.get_dispatcher = patch(self, "otter.metrics.get_dispatcher",
                                    return_value=self.sequence)
Example #16
0
 def get_seq(self, with_cache=True):
     exec_seq = [
         parallel_sequence([
             [(self.gsgi, lambda i: self.gsgi_result)],
             [(("gacd", self.tenant_id, self.group_id, self.now),
              lambda i: (self.servers, ()))]
         ])
     ]
     if with_cache:
         exec_seq.append(
             (UpdateServersCache(
                 self.tenant_id, self.group_id, self.now, self.cache),
              noop)
         )
     return [
         (Log("begin-convergence", {}), noop),
         (Func(datetime.utcnow), lambda i: self.now),
         (MsgWithTime("gather-convergence-data", mock.ANY),
          nested_sequence(exec_seq))
     ]
Example #17
0
    def test_first_error_extraction(self):
        """
        If the GetScalingGroupInfo effect fails, its exception is raised
        directly, without the FirstError wrapper.
        """
        # Perform the GetScalingGroupInfo by raising an exception
        sequence = [
            (Log("begin-convergence", {}), noop),
            (Func(datetime.utcnow), lambda i: self.now),
            (MsgWithTime("gather-convergence-data", mock.ANY),
             nested_sequence([
                parallel_sequence([
                    [(self.gsgi, lambda i: raise_(RuntimeError('foo')))],
                    [("anything", noop)]
                ])
             ]))
        ]

        # And make sure that exception isn't wrapped in FirstError.
        e = self.assertRaises(
            RuntimeError, perform_sequence, sequence, self._invoke(),
            test_dispatcher())
        self.assertEqual(str(e), 'foo')
Example #18
0
    def setUp(self):
        """
        mock dependent functions
        """
        self.connect_cass_servers = patch(
            self, 'otter.metrics.connect_cass_servers')
        self.client = mock.Mock(spec=['disconnect'])
        self.client.disconnect.return_value = succeed(None)
        self.connect_cass_servers.return_value = self.client

        self.log = mock_log()

        self.get_all_metrics = patch(self,
                                     'otter.metrics.get_all_metrics',
                                     return_value=succeed("metrics"))
        self.groups = [{
            "tenantId": "t1",
            "groupId": "g1",
            "launch_config": '{"type": "launch_server"}'
        }, {
            "tenantId": "t1",
            "groupId": "g2",
            "launch_config": '{"type": "launch_server"}'
        }, {
            "tenantId": "t1",
            "groupId": "g12",
            "launch_config": '{"type": "launch_stack"}'
        }, {
            "tenantId": "t3",
            "groupId": "g3",
            "launch_config": '{"type": "launch_stack"}'
        }, {
            "tenantId": "t2",
            "groupId": "g11",
            "launch_config": '{"type": "launch_server"}'
        }]
        self.lc_groups = {"t1": self.groups[:2], "t2": [self.groups[-1]]}

        self.add_to_cloud_metrics = patch(self,
                                          'otter.metrics.add_to_cloud_metrics',
                                          side_effect=intent_func("atcm"))

        self.config = {
            'cassandra': 'c',
            'identity': identity_config,
            'metrics': {
                'service': 'ms',
                'tenant_id': 'tid',
                'region': 'IAD',
                'ttl': 200,
                "last_tenant_fpath": "lpath"
            },
            'region': 'r',
            'cloudServersOpenStack': 'nova',
            'cloudLoadBalancers': 'clb',
            'cloudOrchestration': 'orch',
            'rackconnect': 'rc',
            "non-convergence-tenants": ["ct"]
        }

        self.sequence = SequenceDispatcher([
            (GetAllValidGroups(), const(self.groups)),
            (TenantScope(mock.ANY, "tid"),
             nested_sequence([(("atcm", 200, "r", "metrics", 2, self.config,
                                self.log, False), noop)]))
        ])
        self.get_dispatcher = patch(self,
                                    "otter.metrics.get_dispatcher",
                                    return_value=self.sequence)