예제 #1
0
    def generate_url(self, key):
        """Generate webhook URL with proper format.

        :param key: Key string to be used for decrypt the credentials.
        """
        senlin_creds = context.get_service_context()
        kc = driver_base.SenlinDriver().identity(senlin_creds)
        senlin_service = kc.service_get('clustering', 'senlin')
        if not senlin_service:
            resource = _('service:type=clustering,name=senlin')
            raise exception.ResourceNotFound(resource=resource)
        senlin_service_id = senlin_service['id']
        region = cfg.CONF.region_name_for_services
        endpoint = kc.endpoint_get(senlin_service_id, region, 'public')
        if not endpoint:
            resource = _('endpoint: service=%(service)s,region='
                         '%(region)s,visibility=%(interface)s') % {
                             'service': senlin_service_id,
                             'region': region,
                             'interface': 'public'
                         }
            raise exception.ResourceNotFound(resource=resource)

        endpoint_url = endpoint['url'].replace('$(tenant_id)s', self.project)
        location = endpoint_url + '/webhooks/%s/trigger' % self.id
        location += "?%s" % parse.urlencode({'key': key})

        return location, key
예제 #2
0
    def detach(self, cluster):
        """Routine to be called when the policy is detached from a cluster.

        :param cluster: The cluster from which the policy is to be detached.
        :returns: When the operation was successful, returns a tuple of
            (True, data) where the data contains references to the resources
            created; otherwise returns a tuple of (False, err) where the err
            contains a error message.
        """
        reason = _('LB resources deletion succeeded.')
        params = self._build_conn_params(cluster)
        lb_driver = driver_base.SenlinDriver().loadbalancing(params)

        cp = cluster_policy.ClusterPolicy.load(oslo_context.get_current(),
                                               cluster.id, self.id)

        policy_data = self._extract_policy_data(cp.data)
        if policy_data is None:
            return True, reason

        res, reason = lb_driver.lb_delete(**policy_data)
        if res is False:
            return False, reason

        nodes = node_mod.Node.load_all(oslo_context.get_current(),
                                       cluster_id=cluster.id)
        for node in nodes:
            if 'lb_member' in node.data:
                node.data.pop('lb_member')
                node.store(oslo_context.get_current())

        return True, reason
예제 #3
0
    def heat(self, obj):
        '''Construct heat client using the combined context.'''

        if self.hc:
            return self.hc
        params = self._build_conn_params(obj.user, obj.project)
        self.hc = driver_base.SenlinDriver().orchestration(params)
        return self.hc
예제 #4
0
    def _get_base_url(self):
        base = None
        service_cred = senlin_context.get_service_credentials()
        kc = driver_base.SenlinDriver().identity(service_cred)
        try:
            base = kc.get_senlin_endpoint()
        except exception.InternalError as ex:
            LOG.warning('Senlin endpoint can not be found: %s.', ex)

        return base
예제 #5
0
    def test_init_using_specified_cloud_backend(self):
        plugin2 = mock.Mock()
        plugin2.compute = 'Compute2'
        plugin2.orchestration = 'Orchestration2'
        env = environment.global_env()
        env.register_driver('openstack_test', plugin2)

        sd = driver_base.SenlinDriver('openstack_test')

        self.assertEqual('Compute2', sd.compute)
        self.assertEqual('Orchestration2', sd.orchestration)
예제 #6
0
def get_service_context(**kwargs):
    '''An abstraction layer for getting service credential.

    There could be multiple cloud backends for senlin to use. This
    abstraction layer provides an indirection for senlin to get the
    credentials of 'senlin' user on the specific cloud. By default,
    this credential refers to the credentials built for keystone middleware
    in an OpenStack cloud.
    '''
    identity_service = driver_base.SenlinDriver().identity
    return identity_service.get_service_credentials(**kwargs)
예제 #7
0
    def delete(self, ctx, identifier):
        """Delete an alarm.

        :param identifier: This must be an alarm ID.
        """
        try:
            cc = driver_base.SenlinDriver().telemetry(ctx)
            res = cc.alarm_delete(identifier, True)
            return True, res
        except exc.InternalError as ex:
            return False, six.text_type(ex)
예제 #8
0
    def test_init_using_default_cloud_backend(self):
        plugin1 = mock.Mock()
        plugin1.compute = 'Compute1'
        plugin1.orchestration = 'Orchestration1'
        env = environment.global_env()
        env.register_driver('openstack_test', plugin1)
        cfg.CONF.set_override('cloud_backend', 'openstack_test')

        sd = driver_base.SenlinDriver()

        self.assertEqual('Compute1', sd.compute)
        self.assertEqual('Orchestration1', sd.orchestration)
예제 #9
0
    def keystone(self, user, project):
        """Construct keystone client based on object.

        :param user: The ID of the requesting user.
        :param project: The ID of the requesting project.
        :returns: A reference to the keystone client.
        """
        if self._keystoneclient is not None:
            return self._keystoneclient
        params = self._build_conn_params(user, project)
        self._keystoneclient = driver.SenlinDriver().identity(params)
        return self._keystoneclient
예제 #10
0
    def nova(self, obj):
        """Construct nova client based on object.

        :param obj: Object for which the client is created. It is expected to
                    be None when retrieving an existing client. When creating
                    a client, it conatins the user and project to be used.
        """
        if self._novaclient is not None:
            return self._novaclient
        params = self._build_conn_params(obj)
        self._novaclient = driver.SenlinDriver().compute(params)
        return self._novaclient
예제 #11
0
    def network(self, obj):
        """Construct network client based on object.

        :param obj: Object for which the client is created. It is expected to
                    be None when retrieving an existing client. When creating
                    a client, it contains the user and project to be used.
        """
        if self._networkclient is not None:
            return self._networkclient
        params = self._build_conn_params(obj.user, obj.project)
        self._networkclient = driver_base.SenlinDriver().network(params)
        return self._networkclient
예제 #12
0
    def _get_token(self, **kwargs):
        """Get a valid token based on the credential provided.

        :param cred: Rebuilt credential dictionary for authentication.
        """
        try:
            token = driver_base.SenlinDriver().identity.get_token(**kwargs)
        except Exception as ex:
            LOG.exception('Webhook failed authentication: %s.', ex)
            raise exc.Forbidden()

        return token
예제 #13
0
    def post_op(self, cluster_id, action):
        """Routine to be called after an action has been executed.

        For this particular policy, we take this chance to update the pool
        maintained by the load-balancer.

        :param cluster_id: The ID of the cluster on which a relevant action
            has been executed.
        :param action: The action object that triggered this operation.
        :returns: Nothing.
        """

        # TODO(Yanyanhu): Need special handling for cross-az scenario
        # which is supported by Neutron lbaas.
        creation = action.data.get('creation', None)
        nodes_added = creation.get('nodes', []) if creation else []
        if len(nodes_added) == 0:
            return

        db_cluster = co.Cluster.get(action.context, cluster_id)
        params = self._build_conn_params(db_cluster)
        lb_driver = driver_base.SenlinDriver().loadbalancing(params)
        cp = cluster_policy.ClusterPolicy.load(action.context, cluster_id,
                                               self.id)
        policy_data = self._extract_policy_data(cp.data)
        lb_id = policy_data['loadbalancer']
        pool_id = policy_data['pool']
        port = self.pool_spec.get(self.POOL_PROTOCOL_PORT)
        subnet = self.pool_spec.get(self.POOL_SUBNET)

        # Add new nodes to lb pool
        for node_id in nodes_added:
            node = nm.Node.load(action.context, node_id=node_id)
            member_id = node.data.get('lb_member', None)
            if member_id:
                LOG.warning(_LW('Node %(n)s already in lb pool %(p)s.'), {
                    'n': node_id,
                    'p': pool_id
                })
                continue

            member_id = lb_driver.member_add(node, lb_id, pool_id, port,
                                             subnet)
            if member_id is None:
                action.data['status'] = base.CHECK_ERROR
                action.data['reason'] = _('Failed in adding new node(s) '
                                          'into lb pool.')
                return

            node.data.update({'lb_member': member_id})
            node.store(action.context)

        return
예제 #14
0
    def network(self, user, project):
        """Construct network client based on user and project.

        :param user: The ID of the requesting user.
        :param project: The ID of the requesting project.
        :returns: A reference to the network client.
        """
        if self._networkclient is not None:
            return self._networkclient

        params = self._build_conn_params(user, project)
        self._networkclient = driver.SenlinDriver().network(params)
        return self._networkclient
예제 #15
0
    def lbaas(self, user, project):
        """Construct LB service client based on user and project.

        :param user: The ID of the requesting user.
        :param project: The ID of the requesting project.
        :returns: A reference to the LB service client.
        """
        if self._lbaasclient is not None:
            return self._lbaasclient

        params = self._build_conn_params(user, project)

        self._lbaasclient = driver.SenlinDriver().loadbalancing(params)
        return self._lbaasclient
예제 #16
0
    def test_init_using_default_cloud_backend(self):
        plugin1 = mock.Mock()
        plugin1.compute = 'Compute1'
        plugin1.orchestration = 'Orchestration1'
        env = environment.global_env()
        env.register_driver('cloud_backend_1', plugin1)

        # Using default cloud backend defined in configure file
        cfg.CONF.set_override('cloud_backend',
                              'cloud_backend_1',
                              enforce_type=True)
        sd = driver_base.SenlinDriver()
        self.assertEqual('Compute1', sd.compute)
        self.assertEqual('Orchestration1', sd.orchestration)
예제 #17
0
파일: trust.py 프로젝트: tomas-mazak/senlin
    def _get_trust(self, req):
        """List trusts with current user as the trustor.

        :param req: The WSGI request object.
        :return: ID of the trust or exception of InternalError.
        """
        rpcc = rpc.EngineClient()

        ctx = req.context
        params = {'user': ctx.user_id, 'project': ctx.project_id}
        obj = util.parse_request('CredentialGetRequest', req, params)
        res = rpcc.call(ctx, 'credential_get', obj)
        if res:
            trust_id = res.get('trust', None)
            if trust_id:
                return trust_id

        params = {
            'auth_url': ctx.auth_url,
            'token': ctx.auth_token,
            'project_id': ctx.project_id,
            'user_id': ctx.user_id,
        }
        kc = driver_base.SenlinDriver().identity(params)
        service_cred = context.get_service_credentials()
        admin_id = kc.get_user_id(**service_cred)
        try:
            trust = kc.trust_get_by_trustor(ctx.user_id, admin_id,
                                            ctx.project_id)
        except exception.InternalError as ex:
            if ex.code == 400:
                trust = None
            else:
                raise
        if not trust:
            # Create a trust if no existing one found
            trust = kc.trust_create(ctx.user_id, admin_id, ctx.project_id,
                                    ctx.roles)

        # If credential not exists, create it, otherwise update it.
        cred = {'openstack': {'trust': trust.id}}
        params = {'cred': cred}
        obj = util.parse_request('CredentialCreateRequest', req, params)
        rpcc.call(ctx, 'credential_create', obj)

        return trust.id
예제 #18
0
    def attach(self, cluster):
        """Routine to be invoked when policy is to be attached to a cluster.

        :param cluster: The target cluster to be attached to;
        :returns: When the operation was successful, returns a tuple (True,
                  message); otherwise, return a tuple (False, error).
        """
        res, data = super(LoadBalancingPolicy, self).attach(cluster)
        if res is False:
            return False, data

        nodes = node_mod.Node.load_all(oslo_context.get_current(),
                                       cluster_id=cluster.id)

        params = self._build_conn_params(cluster)
        lb_driver = driver_base.SenlinDriver().loadbalancing(params)

        res, data = lb_driver.lb_create(self.vip_spec, self.pool_spec,
                                        self.hm_spec)
        if res is False:
            return False, data

        port = self.pool_spec.get(self.POOL_PROTOCOL_PORT)
        subnet = self.pool_spec.get(self.POOL_SUBNET)

        for node in nodes:
            member_id = lb_driver.member_add(node, data['loadbalancer'],
                                             data['pool'], port, subnet)
            if member_id is None:
                # When failed in adding member, remove all lb resources that
                # were created and return the failure reason.
                # TODO(anyone): May need to "roll-back" changes caused by any
                # successful member_add() calls.
                lb_driver.lb_delete(**data)
                return False, 'Failed in adding node into lb pool'

            node.data.update({'lb_member': member_id})
            node.store(oslo_context.get_current())

        cluster_data_lb = cluster.data.get('loadbalancers', {})
        cluster_data_lb[self.id] = {'vip_address': data.pop('vip_address')}
        cluster.data['loadbalancers'] = cluster_data_lb

        policy_data = self._build_policy_data(data)

        return True, policy_data
예제 #19
0
    def pre_op(self, cluster_id, action):
        """Routine to be called before an action has been executed.

        For this particular policy, we take this chance to update the pool
        maintained by the load-balancer.

        :param cluster_id: The ID of the cluster on which a relevant action
            has been executed.
        :param action: The action object that triggered this operation.
        :returns: Nothing.
        """

        candidates = self._get_delete_candidates(cluster_id, action)
        if len(candidates) == 0:
            return

        db_cluster = co.Cluster.get(action.context, cluster_id)
        params = self._build_conn_params(db_cluster)
        lb_driver = driver_base.SenlinDriver().loadbalancing(params)
        cp = cluster_policy.ClusterPolicy.load(action.context, cluster_id,
                                               self.id)
        policy_data = self._extract_policy_data(cp.data)
        lb_id = policy_data['loadbalancer']
        pool_id = policy_data['pool']

        # Remove nodes that will be deleted from lb pool
        for node_id in candidates:
            node = nm.Node.load(action.context, node_id=node_id)
            member_id = node.data.get('lb_member', None)
            if member_id is None:
                LOG.warning(_LW('Node %(n)s not found in lb pool %(p)s.'), {
                    'n': node_id,
                    'p': pool_id
                })
                continue

            res = lb_driver.member_remove(lb_id, pool_id, member_id)
            if res is not True:
                action.data['status'] = base.CHECK_ERROR
                action.data['reason'] = _('Failed in removing deleted '
                                          'node(s) from lb pool.')
                return

        return
예제 #20
0
    def attach(self, cluster):
        """Routine to be invoked when policy is to be attached to a cluster.

        :param cluster: The target cluster to be attached to;
        :returns: When the operation was successful, returns a tuple (True,
                  message); otherwise, return a tuple (False, error).
        """
        res, data = super(LoadBalancingPolicy, self).attach(cluster)
        if res is False:
            return False, data

        nodes = node_mod.Node.load_all(oslo_context.get_current(),
                                       cluster_id=cluster.id)

        params = self._build_conn_params(cluster)
        lb_driver = driver_base.SenlinDriver().loadbalancing(params)

        res, data = lb_driver.lb_create(self.vip_spec, self.pool_spec)
        if res is False:
            return False, data

        port = self.pool_spec.get(self.POOL_PROTOCOL_PORT)
        subnet = self.pool_spec.get(self.POOL_SUBNET)

        for node in nodes:
            member_id = lb_driver.member_add(node, data['loadbalancer'],
                                             data['pool'], port, subnet)
            if member_id is None:
                # When failed in adding member, remove all lb resources that
                # were created and return the failure reason.
                # TODO(Yanyan Hu): Maybe we should tolerate member adding
                # failure and allow policy attaching to succeed without
                # all nodes being added into lb pool?
                lb_driver.lb_delete(**data)
                return False, 'Failed in adding node into lb pool'

            node.data.update({'lb_member': member_id})
            node.store(oslo_context.get_current())

        policy_data = self._build_policy_data(data)

        return True, policy_data
예제 #21
0
    def _get_trust(self, ctx):
        """List trusts with current user as the trustor.

        :param ctx: The requesting context.
        :return: ID of the trust or exception of InternalError.
        """
        rpcc = rpc.EngineClient()

        res = rpcc.credential_get(ctx)
        if res:
            trust_id = res.get('trust', None)
            if trust_id:
                return trust_id

        params = {
            'auth_url': ctx.auth_url,
            'token': ctx.auth_token,
            'project_id': ctx.project,
            'user_id': ctx.user,
        }
        kc = driver_base.SenlinDriver().identity(params)
        service_cred = context.get_service_context()
        admin_id = kc.get_user_id(**service_cred)
        try:
            trust = kc.trust_get_by_trustor(ctx.user, admin_id, ctx.project)
        except exception.InternalError as ex:
            if ex.code == 400:
                trust = None
            else:
                raise ex
        if not trust:
            # Create a trust if no existing one found
            trust = kc.trust_create(ctx.user, admin_id, ctx.project, ctx.roles)

        # If credential not exists, create it, otherwise update it.
        rpcc.credential_create(ctx, trust.id)

        return trust.id
예제 #22
0
    def create(self, ctx, **kwargs):
        """Create an alarm for a cluster.

        :param name: The name for the alarm.
        :param urls: A list of URLs for webhooks to be triggered.
        :returns: A dict containing properties of the alarm.
        """
        self.ok_actions = kwargs.get(OK_ACTIONS, [])
        self.alarm_actions = kwargs.get(ALARM_ACTIONS, [])
        self.insufficient_data_actions = kwargs.get(INSUFFICIENT_DATA_ACTIONS,
                                                    [])

        rule_name = self.namespace + '_rule'
        rule_data = dict((k, v) for k, v in self.rule.items())
        params = {
            NAME: self.name,
            DESCRIPTION: self.desc,
            TYPE: self.namespace,
            STATE: self.state,
            SEVERITY: self.severity,
            ENABLED: self.enabled,
            OK_ACTIONS: self.ok_actions,
            ALARM_ACTIONS: self.alarm_actions,
            INSUFFICIENT_DATA_ACTIONS: self.insufficient_data_actions,
            TIME_CONSTRAINTS: self.alarm_properties[TIME_CONSTRAINTS],
            REPEAT: self.alarm_properties[REPEAT],
            rule_name: rule_data,
        }

        try:
            cc = driver_base.SenlinDriver().telemetry(ctx.to_dict())
            alarm = cc.alarm_create(**params)
            self.physical_id = alarm.id
            self.store(ctx)
            return True, alarm.to_dict()
        except exc.SenlinException as ex:
            return False, six.text_type(ex)
예제 #23
0
    def post_op(self, cluster_id, action):
        """Routine to be called after an action has been executed.

        For this particular policy, we take this chance to update the pool
        maintained by the load-balancer.

        :param cluster_id: The ID of the cluster on which a relevant action
            has been executed.
        :param action: The action object that triggered this operation.
        :returns: Nothing.
        """
        nodes_added = action.outputs.get('nodes_added', [])
        nodes_removed = action.outputs.get('nodes_removed', [])
        if ((len(nodes_added) == 0) and (len(nodes_removed) == 0)):
            return

        db_cluster = db_api.cluster_get(action.context, cluster_id)
        params = self._build_conn_params(db_cluster)
        lb_driver = driver_base.SenlinDriver().loadbalancing(params)
        cp = cluster_policy.ClusterPolicy.load(action.context, cluster_id,
                                               self.id)
        policy_data = self._extract_policy_data(cp.data)
        lb_id = policy_data['loadbalancer']
        pool_id = policy_data['pool']
        port = self.pool_spec.get(self.POOL_PROTOCOL_PORT)
        subnet = self.pool_spec.get(self.POOL_SUBNET)

        # Remove nodes that have been deleted from lb pool
        for node_id in nodes_removed:
            node = node_mod.Node.load(action.context, node_id=node_id,
                                      show_deleted=True)
            member_id = node.data.get('lb_member', None)
            if member_id is None:
                LOG.warning(_LW('Node %(n)s not found in lb pool %(p)s.'),
                            {'n': node_id, 'p': pool_id})
                continue

            res = lb_driver.member_remove(lb_id, pool_id, member_id)
            if res is not True:
                action.data['status'] = base.CHECK_ERROR
                action.data['reason'] = _('Failed in removing deleted '
                                          'node(s) from lb pool.')
                return

        # Add new nodes to lb pool
        for node_id in nodes_added:
            node = node_mod.Node.load(action.context, node_id=node_id,
                                      show_deleted=True)
            member_id = node.data.get('lb_member', None)
            if member_id:
                LOG.warning(_LW('Node %(n)s already in lb pool %(p)s.'),
                            {'n': node_id, 'p': pool_id})
                continue

            member_id = lb_driver.member_add(node, lb_id, pool_id, port,
                                             subnet)
            if member_id is None:
                action.data['status'] = base.CHECK_ERROR
                action.data['reason'] = _('Failed in adding new node(s) '
                                          'into lb pool.')
                return

            node.data.update({'lb_member': member_id})
            node.store(action.context)

        return
예제 #24
0
def get_service_context(**kwargs):
    """Get a customized service context."""
    identity_service = driver_base.SenlinDriver().identity
    creds = identity_service.get_service_credentials(**kwargs)
    return RequestContext.from_dict(creds)
예제 #25
0
 def zaqar(self):
     if self._zaqarclient is not None:
         return self._zaqarclient
     params = self._build_conn_params(self.user, self.project)
     self._zaqarclient = driver_base.SenlinDriver().message(params)
     return self._zaqarclient
예제 #26
0
 def keystone(self):
     if self._keystoneclient is not None:
         return self._keystoneclient
     params = self._build_conn_params(self.user, self.project)
     self._keystoneclient = driver_base.SenlinDriver().identity(params)
     return self._keystoneclient
예제 #27
0
 def workflow(self, obj):
     if self._workflowclient is not None:
         return self._workflowclient
     params = self._build_conn_params(obj.user, obj.project)
     self._workflowclient = driver_base.SenlinDriver().workflow(params)
     return self._workflowclient