Example #1
0
    def test_create_counter_proposal(self):

        with self.assertRaises(BadRequest) as cm:
            consumer_accept_sap = Negotiation.create_counter_proposal(proposal_status=ProposalStatusEnum.INITIAL)
        self.assertIn('The negotiation parameter must be a valid Negotiation object',cm.exception.message)

        negotiation_handler = Negotiation(self)

        sap = IonObject(OT.EnrollmentProposal,consumer=self.actor_identity._id, provider=self.org._id )

        negotiation = Mock()
        negotiation._id = '456'
        negotiation.type_ = RT.Negotiation
        negotiation.proposals = [sap]

        self.mock_read.return_value = negotiation
        self.mock_create.return_value = ['456', 2]

        neg_id = negotiation_handler.create_negotiation(sap)

        sap.negotiation_id = neg_id

        consumer_accept_sap = Negotiation.create_counter_proposal(negotiation, proposal_status=ProposalStatusEnum.COUNTER,
                originator=ProposalOriginatorEnum.PROVIDER)

        self.assertEqual(consumer_accept_sap.negotiation_id, negotiation._id)
        self.assertEqual(len(negotiation.proposals),1)
        self.assertEqual(consumer_accept_sap.sequence_num, len(negotiation.proposals))
        self.assertEqual(consumer_accept_sap.proposal_status, ProposalStatusEnum.COUNTER)
        self.assertEqual(consumer_accept_sap.originator, ProposalOriginatorEnum.PROVIDER)
    def test_get_extended_user_identity(self):

        actor_identity_obj = IonObject("ActorIdentity", {"name": self.subject})
        actor_id = self.identity_management_service.create_actor_identity(actor_identity_obj)

        user_credentials_obj = IonObject("UserCredentials", {"name": self.subject})
        self.identity_management_service.register_user_credentials(actor_id, user_credentials_obj)

        user_info_obj = IonObject("UserInfo", {"name": "Foo"})
        user_info_id = self.identity_management_service.create_user_info(actor_id, user_info_obj)

        ion_org = self.org_client.find_org()

        #Build the Service Agreement Proposal to to request a role but never close it
        sap = IonObject(OT.RequestRoleProposal,consumer=actor_id, provider=ion_org._id, role_name=ORG_MANAGER_ROLE )
        sap_response = self.org_client.negotiate(sap)

        #Just grant the role anyway
        #self.org_client.grant_role(ion_org._id, actor_id, ORG_MANAGER_ROLE)

        with self.assertRaises(NotFound):
            self.identity_management_service.get_user_info_extension('That rug really tied the room together.')
        with self.assertRaises(BadRequest):
            self.identity_management_service.get_user_info_extension()

        #Check the user without the negotiation role request
        extended_user = self.identity_management_service.get_user_info_extension(user_info_id, org_id=ion_org._id)
        self.assertEqual(user_info_obj.type_,extended_user.resource.type_)
        self.assertEqual(len(extended_user.roles),1)
        self.assertEqual(len(extended_user.open_requests),1)
        self.assertEqual(extended_user.open_requests[0].org_id, ion_org._id)
        self.assertEqual(extended_user.open_requests[0].user_id, user_info_id)
        self.assertEqual(extended_user.open_requests[0].request_type, OT.RequestRoleProposal)
        self.assertEqual(len(extended_user.closed_requests),0)
        self.assertEqual(extended_user.open_requests[0]._id, extended_user.open_requests[0].negotiation_id)

        neg = self.resource_registry.read(object_id=extended_user.open_requests[0].negotiation_id)
        sap_response = Negotiation.create_counter_proposal(neg, ProposalStatusEnum.ACCEPTED, ProposalOriginatorEnum.PROVIDER)
        sap_response2 = self.org_client.negotiate(sap_response)

        #Now check the user after the negotiation has been accepted and the role granted
        extended_user = self.identity_management_service.get_user_info_extension(user_info_id, org_id=ion_org._id)
        self.assertEqual(user_info_obj.type_,extended_user.resource.type_)
        self.assertEqual(len(extended_user.roles),2)
        self.assertEqual(len(extended_user.open_requests),0)
        self.assertEqual(len(extended_user.closed_requests),1)
        self.assertEqual(extended_user.closed_requests[0].org_id, ion_org._id)
        self.assertEqual(extended_user.closed_requests[0].user_id, user_info_id)
        self.assertEqual(extended_user.closed_requests[0].request_type, OT.RequestRoleProposal)

        self.identity_management_service.delete_user_info(user_info_id)

        self.org_client.revoke_role(org_id=ion_org._id, actor_id=actor_id, role_name=ORG_MANAGER_ROLE)

        self.identity_management_service.unregister_user_credentials(actor_id, self.subject)

        self.identity_management_service.delete_actor_identity(actor_id)
    def test_get_extended_user_identity(self):

        actor_identity_obj = IonObject("ActorIdentity", {"name": self.subject})
        actor_id = self.identity_management_service.create_actor_identity(actor_identity_obj)

        user_credentials_obj = IonObject("UserCredentials", {"name": self.subject})
        self.identity_management_service.register_user_credentials(actor_id, user_credentials_obj)

        user_info_obj = IonObject("UserInfo", {"name": "Foo"})
        user_info_id = self.identity_management_service.create_user_info(actor_id, user_info_obj)

        ion_org = self.org_client.find_org()

        #Build the Service Agreement Proposal to to request a role but never close it
        sap = IonObject(OT.RequestRoleProposal,consumer=actor_id, provider=ion_org._id, role_name=ORG_MANAGER_ROLE )
        sap_response = self.org_client.negotiate(sap)

        #Just grant the role anyway
        #self.org_client.grant_role(ion_org._id, actor_id, ORG_MANAGER_ROLE)

        with self.assertRaises(NotFound):
            self.identity_management_service.get_user_info_extension('That rug really tied the room together.')
        with self.assertRaises(BadRequest):
            self.identity_management_service.get_user_info_extension()

        #Check the user without the negotiation role request
        extended_user = self.identity_management_service.get_user_info_extension(user_info_id, org_id=ion_org._id)
        self.assertEqual(user_info_obj.type_,extended_user.resource.type_)
        self.assertEqual(len(extended_user.roles),1)
        self.assertEqual(len(extended_user.open_requests),1)
        self.assertEqual(extended_user.open_requests[0].org_id, ion_org._id)
        self.assertEqual(extended_user.open_requests[0].user_id, user_info_id)
        self.assertEqual(extended_user.open_requests[0].request_type, OT.RequestRoleProposal)
        self.assertEqual(len(extended_user.closed_requests),0)
        self.assertEqual(extended_user.open_requests[0]._id, extended_user.open_requests[0].negotiation_id)

        neg = self.resource_registry.read(object_id=extended_user.open_requests[0].negotiation_id)
        sap_response = Negotiation.create_counter_proposal(neg, ProposalStatusEnum.ACCEPTED, ProposalOriginatorEnum.PROVIDER)
        sap_response2 = self.org_client.negotiate(sap_response)

        #Now check the user after the negotiation has been accepted and the role granted
        extended_user = self.identity_management_service.get_user_info_extension(user_info_id, org_id=ion_org._id)
        self.assertEqual(user_info_obj.type_,extended_user.resource.type_)
        self.assertEqual(len(extended_user.roles),2)
        self.assertEqual(len(extended_user.open_requests),0)
        self.assertEqual(len(extended_user.closed_requests),1)
        self.assertEqual(extended_user.closed_requests[0].org_id, ion_org._id)
        self.assertEqual(extended_user.closed_requests[0].user_id, user_info_id)
        self.assertEqual(extended_user.closed_requests[0].request_type, OT.RequestRoleProposal)

        self.identity_management_service.delete_user_info(user_info_id)

        self.org_client.revoke_role(org_id=ion_org._id, actor_id=actor_id, role_name=ORG_MANAGER_ROLE)

        self.identity_management_service.unregister_user_credentials(actor_id, self.subject)

        self.identity_management_service.delete_actor_identity(actor_id)
Example #4
0
    def test_create_counter_proposal(self):

        with self.assertRaises(BadRequest) as cm:
            consumer_accept_sap = Negotiation.create_counter_proposal(
                proposal_status=ProposalStatusEnum.INITIAL)
        self.assertIn(
            'The negotiation parameter must be a valid Negotiation object',
            cm.exception.message)

        negotiation_handler = Negotiation(self)

        sap = IonObject(OT.EnrollmentProposal,
                        consumer=self.actor_identity._id,
                        provider=self.org._id)

        negotiation = Mock()
        negotiation._id = '456'
        negotiation.type_ = RT.Negotiation
        negotiation.proposals = [sap]

        self.mock_read.return_value = negotiation
        self.mock_create.return_value = ['456', 2]

        neg_id = negotiation_handler.create_negotiation(sap)

        sap.negotiation_id = neg_id

        consumer_accept_sap = Negotiation.create_counter_proposal(
            negotiation,
            proposal_status=ProposalStatusEnum.COUNTER,
            originator=ProposalOriginatorEnum.PROVIDER)

        self.assertEqual(consumer_accept_sap.negotiation_id, negotiation._id)
        self.assertEqual(len(negotiation.proposals), 1)
        self.assertEqual(consumer_accept_sap.sequence_num,
                         len(negotiation.proposals))
        self.assertEqual(consumer_accept_sap.proposal_status,
                         ProposalStatusEnum.COUNTER)
        self.assertEqual(consumer_accept_sap.originator,
                         ProposalOriginatorEnum.PROVIDER)
def resolve_org_negotiation():
    try:
        payload = request.form['payload']
        json_params = simplejson.loads(str(payload))

        ion_actor_id, expiry = get_governance_info_from_request(
            'serviceRequest', json_params)
        ion_actor_id, expiry = validate_request(ion_actor_id, expiry)
        headers = build_message_headers(ion_actor_id, expiry)

        # extract negotiation-specific data (convert from unicode just in case - these are machine generated and unicode specific
        # chars are unexpected)
        verb = str(json_params['verb'])
        originator = str(json_params['originator'])
        negotiation_id = str(json_params['negotiation_id'])
        reason = str(json_params.get('reason', ''))

        proposal_status = None
        if verb.lower() == "accept":
            proposal_status = ProposalStatusEnum.ACCEPTED
        elif verb.lower() == "reject":
            proposal_status = ProposalStatusEnum.REJECTED

        proposal_originator = None
        if originator.lower() == "consumer":
            proposal_originator = ProposalOriginatorEnum.CONSUMER
        elif originator.lower() == "provider":
            proposal_originator = ProposalOriginatorEnum.PROVIDER

        rr_client = ResourceRegistryServiceProcessClient(
            node=Container.instance.node, process=service_gateway_instance)
        negotiation = rr_client.read(negotiation_id, headers=headers)

        new_negotiation_sap = Negotiation.create_counter_proposal(
            negotiation, proposal_status, proposal_originator)

        org_client = OrgManagementServiceProcessClient(
            node=Container.instance.node, process=service_gateway_instance)
        resp = org_client.negotiate(new_negotiation_sap, headers=headers)

        # update reason if it exists
        if reason:
            # reload negotiation because it has changed
            negotiation = rr_client.read(negotiation_id, headers=headers)
            negotiation.reason = reason
            rr_client.update(negotiation)

        return gateway_json_response(resp)

    except Exception, e:
        return build_error_response(e)
def resolve_org_negotiation():
    try:
        payload              = request.form['payload']
        json_params          = json_loads(str(payload))

        ion_actor_id, expiry = get_governance_info_from_request('serviceRequest', json_params)
        ion_actor_id, expiry = validate_request(ion_actor_id, expiry)
        headers              = build_message_headers(ion_actor_id, expiry)

        # extract negotiation-specific data (convert from unicode just in case - these are machine generated and unicode specific
        # chars are unexpected)
        verb                 = str(json_params['verb'])
        originator           = str(json_params['originator'])
        negotiation_id       = str(json_params['negotiation_id'])
        reason               = str(json_params.get('reason', ''))

        proposal_status = None
        if verb.lower() == "accept":
            proposal_status = ProposalStatusEnum.ACCEPTED
        elif verb.lower() == "reject":
            proposal_status = ProposalStatusEnum.REJECTED

        proposal_originator = None
        if originator.lower() == "consumer":
            proposal_originator = ProposalOriginatorEnum.CONSUMER
        elif originator.lower() == "provider":
            proposal_originator = ProposalOriginatorEnum.PROVIDER

        rr_client = ResourceRegistryServiceProcessClient(process=service_gateway_instance)
        negotiation = rr_client.read(negotiation_id, headers=headers)

        new_negotiation_sap = Negotiation.create_counter_proposal(negotiation, proposal_status, proposal_originator)

        org_client = OrgManagementServiceProcessClient(process=service_gateway_instance)
        resp = org_client.negotiate(new_negotiation_sap, headers=headers)

        # update reason if it exists
        if reason:
            # reload negotiation because it has changed
            negotiation = rr_client.read(negotiation_id, headers=headers)
            negotiation.reason = reason
            rr_client.update(negotiation)

        return gateway_json_response(resp)

    except Exception as e:
        return build_error_response(e)
    def negotiate(self, sap=None):
        """A generic operation for negotiating actions with an Org, such as for enrollment, role request or to acquire a
        resource managed by the Org. The Service Agreement Proposal is used to specify conditions of the proposal as well
        as counter proposals and the Org will create Negotiation Resource to track the history and status of the negotiation.

        @param sap    ServiceAgreementProposal
        @retval sap    ServiceAgreementProposal
        @throws BadRequest    If an SAP is not provided or incomplete
        @throws Inconsistent    If an SAP has inconsistent information
        @throws NotFound    If any of the ids in the SAP do not exist
        """

        if sap is None or ( sap.type_ != OT.ServiceAgreementProposal and not issubtype(sap.type_, OT.ServiceAgreementProposal)):
            raise BadRequest('The sap parameter must be a valid Service Agreement Proposal object')

        if sap.proposal_status == ProposalStatusEnum.INITIAL:
            neg_id = self.negotiation_handler.create_negotiation(sap)

            org = self.read_org(org_id=sap.provider)

            #Publish an event indicating an Negotiation has been initiated
            self.event_pub.publish_event(event_type=OT.OrgNegotiationInitiatedEvent, origin=org._id, origin_type='Org',
                description=sap.description, org_name=org.name, negotiation_id=neg_id, sub_type=sap.type_ )

            #Synchronize the internal reference for later use
            sap.negotiation_id = neg_id

        #Get the most recent version of the Negotiation resource
        negotiation = self.negotiation_handler.read_negotiation(sap)

        #Update the Negotiation object with the latest SAP
        neg_id = self.negotiation_handler.update_negotiation(sap)

        #Get the most recent version of the Negotiation resource
        negotiation = self.clients.resource_registry.read(neg_id)

        #hardcodng some rules at the moment - could be replaced by a Rules Engine
        if sap.type_ == OT.AcquireResourceExclusiveProposal:

            if self.is_resource_acquired_exclusively(None, sap.resource_id):
                #Automatically accept the proposal for exclusive access if it is not already acquired exclusively
                provider_accept_sap = Negotiation.create_counter_proposal(negotiation, ProposalStatusEnum.REJECTED, ProposalOriginatorEnum.PROVIDER)

                rejection_reason = "The resource has already been acquired exclusively"

                #Update the Negotiation object with the latest SAP
                neg_id = self.negotiation_handler.update_negotiation(provider_accept_sap, rejection_reason)

                #Get the most recent version of the Negotiation resource
                negotiation = self.clients.resource_registry.read(neg_id)

            else:

                #Automatically reject the proposal if the exipration request is greater than 12 hours from now or 0
                cur_time = int(get_ion_ts())
                expiration = int(cur_time +  ( 12 * 60 * 60 * 1000 )) # 12 hours from now
                if int(sap.expiration) == 0 or int(sap.expiration) > expiration:
                    #Automatically accept the proposal for exclusive access if it is not already acquired exclusively
                    provider_accept_sap = Negotiation.create_counter_proposal(negotiation, ProposalStatusEnum.REJECTED, ProposalOriginatorEnum.PROVIDER)

                    rejection_reason = "A proposal to acquire a resource exclusively must be more than 0 and be less than 12 hours."

                    #Update the Negotiation object with the latest SAP
                    neg_id = self.negotiation_handler.update_negotiation(provider_accept_sap, rejection_reason)

                    #Get the most recent version of the Negotiation resource
                    negotiation = self.clients.resource_registry.read(neg_id)

                else:

                    #Automatically accept the proposal for exclusive access if it is not already acquired exclusively
                    provider_accept_sap = Negotiation.create_counter_proposal(negotiation, ProposalStatusEnum.ACCEPTED, ProposalOriginatorEnum.PROVIDER)

                    #Update the Negotiation object with the latest SAP
                    neg_id = self.negotiation_handler.update_negotiation(provider_accept_sap)

                    #Get the most recent version of the Negotiation resource
                    negotiation = self.clients.resource_registry.read(neg_id)

        #Check to see if the rules allow for auto acceptance of the negotiations - where the second party is assumed to accept if the
        #first party accepts.
        if negotiation_rules[sap.type_]['auto_accept']:

            #Automatically accept for the consumer if the Org Manager as provider accepts the proposal
            latest_sap = negotiation.proposals[-1]

            if latest_sap.proposal_status == ProposalStatusEnum.ACCEPTED and latest_sap.originator == ProposalOriginatorEnum.PROVIDER:
                consumer_accept_sap = Negotiation.create_counter_proposal(negotiation, ProposalStatusEnum.ACCEPTED)

                #Update the Negotiation object with the latest SAP
                neg_id = self.negotiation_handler.update_negotiation(consumer_accept_sap)

                #Get the most recent version of the Negotiation resource
                negotiation = self.clients.resource_registry.read(neg_id)

            elif latest_sap.proposal_status == ProposalStatusEnum.ACCEPTED and latest_sap.originator == ProposalOriginatorEnum.CONSUMER:
                provider_accept_sap = Negotiation.create_counter_proposal(negotiation, ProposalStatusEnum.ACCEPTED, ProposalOriginatorEnum.PROVIDER)

                #Update the Negotiation object with the latest SAP
                neg_id = self.negotiation_handler.update_negotiation(provider_accept_sap)

                #Get the most recent version of the Negotiation resource
                negotiation = self.clients.resource_registry.read(neg_id)


        #Return the latest proposal
        return negotiation.proposals[-1]
Example #8
0
    def negotiate(self, sap=None):
        """A generic operation for negotiating actions with an Org, such as for enrollment, role request
        or to acquire a resource managed by the Org. The ServiceAgreementProposal object is used to
        specify conditions of the proposal as well as counter proposals and the Org will create a
        Negotiation resource to track the history and status of the negotiation.
        """

        if sap is None or (
                sap.type_ != OT.ServiceAgreementProposal
                and not issubtype(sap.type_, OT.ServiceAgreementProposal)):
            raise BadRequest(
                "The sap argument must be a valid ServiceAgreementProposal object"
            )

        if sap.proposal_status == ProposalStatusEnum.INITIAL:
            neg_id = self.negotiation_handler.create_negotiation(sap)

            org = self.read_org(org_id=sap.provider)

            # Publish an event indicating an Negotiation has been initiated
            self.event_pub.publish_event(
                event_type=OT.OrgNegotiationInitiatedEvent,
                origin=org._id,
                origin_type="Org",
                description=sap.description,
                org_name=org.name,
                negotiation_id=neg_id,
                sub_type=sap.type_)

            # Synchronize the internal reference for later use
            sap.negotiation_id = neg_id

        # Get the most recent version of the Negotiation resource
        negotiation = self.negotiation_handler.read_negotiation(sap)

        # Update the Negotiation object with the latest SAP
        neg_id = self.negotiation_handler.update_negotiation(sap)

        # Get the most recent version of the Negotiation resource
        negotiation = self.rr.read(neg_id)

        # hardcoding some rules at the moment - could be replaced by a Rules Engine
        if sap.type_ == OT.AcquireResourceExclusiveProposal:

            if self.is_resource_acquired_exclusively(None, sap.resource_id):
                # Automatically accept the proposal for exclusive access if it is not already acquired exclusively
                provider_accept_sap = Negotiation.create_counter_proposal(
                    negotiation, ProposalStatusEnum.REJECTED,
                    ProposalOriginatorEnum.PROVIDER)

                rejection_reason = "The resource has already been acquired exclusively"

                # Update the Negotiation object with the latest SAP
                neg_id = self.negotiation_handler.update_negotiation(
                    provider_accept_sap, rejection_reason)

                # Get the most recent version of the Negotiation resource
                negotiation = self.rr.read(neg_id)

            else:
                # Automatically reject the proposal if the expiration request is greater than 12 hours from now or 0
                cur_time = int(get_ion_ts())
                expiration = int(cur_time +
                                 (12 * 60 * 60 * 1000))  # 12 hours from now
                if int(sap.expiration) == 0 or int(
                        sap.expiration) > expiration:
                    # Automatically accept the proposal for exclusive access if it is not already acquired exclusively
                    provider_accept_sap = Negotiation.create_counter_proposal(
                        negotiation, ProposalStatusEnum.REJECTED,
                        ProposalOriginatorEnum.PROVIDER)

                    rejection_reason = "A proposal to acquire a resource exclusively must be more than 0 and be less than 12 hours."

                    # Update the Negotiation object with the latest SAP
                    neg_id = self.negotiation_handler.update_negotiation(
                        provider_accept_sap, rejection_reason)

                    # Get the most recent version of the Negotiation resource
                    negotiation = self.rr.read(neg_id)

                else:
                    # Automatically accept the proposal for exclusive access if it is not already acquired exclusively
                    provider_accept_sap = Negotiation.create_counter_proposal(
                        negotiation, ProposalStatusEnum.ACCEPTED,
                        ProposalOriginatorEnum.PROVIDER)

                    # Update the Negotiation object with the latest SAP
                    neg_id = self.negotiation_handler.update_negotiation(
                        provider_accept_sap)

                    # Get the most recent version of the Negotiation resource
                    negotiation = self.rr.read(neg_id)

        # Check to see if the rules allow for auto acceptance of the negotiations -
        # where the second party is assumed to accept if the
        # first party accepts.
        if negotiation_rules[sap.type_]["auto_accept"]:
            # Automatically accept for the consumer if the Org Manager as provider accepts the proposal
            latest_sap = negotiation.proposals[-1]

            if latest_sap.proposal_status == ProposalStatusEnum.ACCEPTED and latest_sap.originator == ProposalOriginatorEnum.PROVIDER:
                consumer_accept_sap = Negotiation.create_counter_proposal(
                    negotiation, ProposalStatusEnum.ACCEPTED)

                # Update the Negotiation object with the latest SAP
                neg_id = self.negotiation_handler.update_negotiation(
                    consumer_accept_sap)

                # Get the most recent version of the Negotiation resource
                negotiation = self.rr.read(neg_id)

            elif latest_sap.proposal_status == ProposalStatusEnum.ACCEPTED and latest_sap.originator == ProposalOriginatorEnum.CONSUMER:
                provider_accept_sap = Negotiation.create_counter_proposal(
                    negotiation, ProposalStatusEnum.ACCEPTED,
                    ProposalOriginatorEnum.PROVIDER)

                # Update the Negotiation object with the latest SAP
                neg_id = self.negotiation_handler.update_negotiation(
                    provider_accept_sap)

                # Get the most recent version of the Negotiation resource
                negotiation = self.rr.read(neg_id)

        # Return the latest proposal
        return negotiation.proposals[-1]
Example #9
0
    def test_update_negotiation(self):

        self.preconditions.check_method1.return_value = True
        self.preconditions.check_method2.return_value = False
        self.accept_actions.accept_method.return_value = None

        negotiation_rules = {
            OT.EnrollmentProposal: {
                'pre_conditions': ['preconditions.check_method1(sap.consumer)', 'not preconditions.check_method2(sap.provider,sap.consumer)'],
                'accept_action': 'accept_actions.accept_method(sap.provider,sap.consumer)'
            }}

        negotiation_handler = Negotiation(self, negotiation_rules, self.event_pub)

        with self.assertRaises(Inconsistent) as cm:
            negotiation_handler.update_negotiation()
        self.assertIn('The Service Agreement Proposal must have a negotiation resource id associated with it',cm.exception.message)

        sap = IonObject(OT.EnrollmentProposal,consumer=self.actor_identity._id, provider=self.org._id )

        with self.assertRaises(Inconsistent) as cm:
            negotiation_handler.update_negotiation(sap)
        self.assertIn('The Service Agreement Proposal must have a negotiation resource id associated with it',cm.exception.message)

        negotiation = Mock()
        negotiation._id = '456'
        negotiation.type_ = RT.Negotiation
        negotiation.proposals = []

        sap.negotiation_id = negotiation._id

        self.mock_read.return_value = negotiation
        self.mock_update.return_value = ['456', 2]


        neg_id = negotiation_handler.update_negotiation(sap)

        self.assertEqual(self.event_pub.publish_event.called,True)

        self.assertEqual(neg_id, negotiation._id)
        self.assertEqual(len(negotiation.proposals),1)

        counter_sap = Negotiation.create_counter_proposal(negotiation, ProposalStatusEnum.REJECTED, ProposalOriginatorEnum.PROVIDER)

        neg_id = negotiation_handler.update_negotiation(counter_sap, 'Fake rejection reason')

        self.assertEqual(len(negotiation.proposals),2)
        self.assertEqual(negotiation.negotiation_status, NegotiationStatusEnum.REJECTED)
        self.assertEquals(negotiation.reason, 'Fake rejection reason' )

        counter_sap = Negotiation.create_counter_proposal(negotiation, ProposalStatusEnum.ACCEPTED, ProposalOriginatorEnum.PROVIDER)

        neg_id = negotiation_handler.update_negotiation(counter_sap)
        self.assertEqual(len(negotiation.proposals),3)
        self.assertEqual(negotiation.negotiation_status, NegotiationStatusEnum.REJECTED)

        counter_sap = Negotiation.create_counter_proposal(negotiation, ProposalStatusEnum.ACCEPTED, ProposalOriginatorEnum.CONSUMER)

        neg_id = negotiation_handler.update_negotiation(counter_sap)
        self.assertEqual(len(negotiation.proposals),4)
        self.assertEqual(negotiation.negotiation_status, NegotiationStatusEnum.ACCEPTED)

        self.assertEqual(self.accept_actions.accept_method.called,True)
Example #10
0
    def test_update_negotiation(self):

        self.preconditions.check_method1.return_value = True
        self.preconditions.check_method2.return_value = False
        self.accept_actions.accept_method.return_value = None

        negotiation_rules = {
            OT.EnrollmentProposal: {
                'pre_conditions': [
                    'preconditions.check_method1(sap.consumer)',
                    'not preconditions.check_method2(sap.provider,sap.consumer)'
                ],
                'accept_action':
                'accept_actions.accept_method(sap.provider,sap.consumer)'
            }
        }

        negotiation_handler = Negotiation(self, negotiation_rules)

        with self.assertRaises(Inconsistent) as cm:
            negotiation_handler.update_negotiation()
        self.assertIn(
            'The Service Agreement Proposal must have a negotiation resource id associated with it',
            cm.exception.message)

        sap = IonObject(OT.EnrollmentProposal,
                        consumer=self.actor_identity._id,
                        provider=self.org._id)

        with self.assertRaises(Inconsistent) as cm:
            negotiation_handler.update_negotiation(sap)
        self.assertIn(
            'The Service Agreement Proposal must have a negotiation resource id associated with it',
            cm.exception.message)

        negotiation = Mock()
        negotiation._id = '456'
        negotiation.type_ = RT.Negotiation
        negotiation.proposals = []

        sap.negotiation_id = negotiation._id

        self.mock_read.return_value = negotiation
        self.mock_update.return_value = ['456', 2]

        neg_id = negotiation_handler.update_negotiation(sap)

        self.assertEqual(self.event_pub.publish_event.called, True)

        self.assertEqual(neg_id, negotiation._id)
        self.assertEqual(len(negotiation.proposals), 1)

        counter_sap = Negotiation.create_counter_proposal(
            negotiation, ProposalStatusEnum.REJECTED,
            ProposalOriginatorEnum.PROVIDER)

        neg_id = negotiation_handler.update_negotiation(
            counter_sap, 'Fake rejection reason')

        self.assertEqual(len(negotiation.proposals), 2)
        self.assertEqual(negotiation.negotiation_status,
                         NegotiationStatusEnum.REJECTED)
        self.assertEquals(negotiation.reason, 'Fake rejection reason')

        counter_sap = Negotiation.create_counter_proposal(
            negotiation, ProposalStatusEnum.ACCEPTED,
            ProposalOriginatorEnum.PROVIDER)

        neg_id = negotiation_handler.update_negotiation(counter_sap)
        self.assertEqual(len(negotiation.proposals), 3)
        self.assertEqual(negotiation.negotiation_status,
                         NegotiationStatusEnum.REJECTED)

        counter_sap = Negotiation.create_counter_proposal(
            negotiation, ProposalStatusEnum.ACCEPTED,
            ProposalOriginatorEnum.CONSUMER)

        neg_id = negotiation_handler.update_negotiation(counter_sap)
        self.assertEqual(len(negotiation.proposals), 4)
        self.assertEqual(negotiation.negotiation_status,
                         NegotiationStatusEnum.ACCEPTED)

        self.assertEqual(self.accept_actions.accept_method.called, True)
    def negotiate(self, sap=None):
        """A generic operation for negotiating actions with an Org, such as for enrollment, role request or to acquire a
        resource managed by the Org. The Service Agreement Proposal is used to specify conditions of the proposal as well
        as counter proposals and the Org will create Negotiation Resource to track the history and status of the negotiation.

        @param sap    ServiceAgreementProposal
        @retval sap    ServiceAgreementProposal
        @throws BadRequest    If an SAP is not provided or incomplete
        @throws Inconsistent    If an SAP has inconsistent information
        @throws NotFound    If any of the ids in the SAP do not exist
        """

        if sap is None or ( sap.type_ != OT.ServiceAgreementProposal and not issubtype(sap.type_, OT.ServiceAgreementProposal)):
            raise BadRequest('The sap parameter must be a valid Service Agreement Proposal object')

        if sap.proposal_status == ProposalStatusEnum.INITIAL:
            neg_id = self.negotiation_handler.create_negotiation(sap)

            #Synchronize the internal reference for later use
            sap.negotiation_id = neg_id

        #Get the most recent version of the Negotiation resource
        negotiation = self.negotiation_handler.read_negotiation(sap)

        #Update the Negotiation object with the latest SAP
        neg_id = self.negotiation_handler.update_negotiation(sap)

        #Get the most recent version of the Negotiation resource
        negotiation = self.clients.resource_registry.read(neg_id)

        #hardcodng some rules at the moment
        if sap.type_ == OT.EnrollmentProposal or sap.type_ == OT.RequestRoleProposal:
            #Automatically accept for the consumer if the Org Manager as provider accepts the proposal
            if sap.proposal_status == ProposalStatusEnum.ACCEPTED and sap.originator == ProposalOriginatorEnum.PROVIDER:
                consumer_accept_sap = Negotiation.create_counter_proposal(negotiation, ProposalStatusEnum.ACCEPTED)

                #Update the Negotiation object with the latest SAP
                neg_id = self.negotiation_handler.update_negotiation(consumer_accept_sap)

                #Get the most recent version of the Negotiation resource
                negotiation = self.clients.resource_registry.read(neg_id)

            elif sap.proposal_status == ProposalStatusEnum.ACCEPTED and sap.originator == ProposalOriginatorEnum.CONSUMER:
                provider_accept_sap = Negotiation.create_counter_proposal(negotiation, ProposalStatusEnum.ACCEPTED, ProposalOriginatorEnum.PROVIDER)

                #Update the Negotiation object with the latest SAP
                neg_id = self.negotiation_handler.update_negotiation(provider_accept_sap)

                #Get the most recent version of the Negotiation resource
                negotiation = self.clients.resource_registry.read(neg_id)

        elif sap.type_ == OT.AcquireResourceExclusiveProposal:
            if not self.is_resource_acquired_exclusively(None, sap.resource):

                #Automatically reject the proposal if the exipration request is greater than 12 hours from now or 0
                cur_time = int(get_ion_ts())
                expiration = cur_time +  ( 12 * 60 * 60 * 1000 ) # 12 hours from now
                if sap.expiration == 0 or sap.expiration > expiration:
                    #Automatically accept the proposal for exclusive access if it is not already acquired exclusively
                    provider_accept_sap = Negotiation.create_counter_proposal(negotiation, ProposalStatusEnum.REJECTED, ProposalOriginatorEnum.PROVIDER)

                    rejection_reason = "A proposal to acquire a resource exclusively must be included and be less than 12 hours."

                    #Update the Negotiation object with the latest SAP
                    neg_id = self.negotiation_handler.update_negotiation(provider_accept_sap, rejection_reason)

                    #Get the most recent version of the Negotiation resource
                    negotiation = self.clients.resource_registry.read(neg_id)
                else:

                    #Automatically accept the proposal for exclusive access if it is not already acquired exclusively
                    provider_accept_sap = Negotiation.create_counter_proposal(negotiation, ProposalStatusEnum.ACCEPTED, ProposalOriginatorEnum.PROVIDER)

                    #Update the Negotiation object with the latest SAP
                    neg_id = self.negotiation_handler.update_negotiation(provider_accept_sap)

                    #Get the most recent version of the Negotiation resource
                    negotiation = self.clients.resource_registry.read(neg_id)

                    consumer_accept_sap = Negotiation.create_counter_proposal(negotiation, ProposalStatusEnum.ACCEPTED)

                    #Update the Negotiation object with the latest SAP
                    neg_id = self.negotiation_handler.update_negotiation(consumer_accept_sap)

                    #Get the most recent version of the Negotiation resource
                    negotiation = self.clients.resource_registry.read(neg_id)

        #Return the latest proposal
        return negotiation.proposals[-1]