osaf/libs/agents/saf/imma/imma_oi_api.c | 6 - osaf/services/saf/immsv/README | 84 +++++++++++++++++++- osaf/services/saf/immsv/immnd/ImmModel.cc | 14 +++ osaf/tools/safimm/immadm/imm_admin.c | 7 +- tests/immsv/implementer/test_SaImmOiAdminOperation.c | 34 ++++++- 5 files changed, 131 insertions(+), 14 deletions(-)
This enhancement (#799) extends the scope of the existing OpenSAF API for administrative-operations such that it supports the direct invocation of admin-operations on an implementer or applier. See the included patch of: osaf/services/saf/immsv/README for details. diff --git a/osaf/libs/agents/saf/imma/imma_oi_api.c b/osaf/libs/agents/saf/imma/imma_oi_api.c --- a/osaf/libs/agents/saf/imma/imma_oi_api.c +++ b/osaf/libs/agents/saf/imma/imma_oi_api.c @@ -901,12 +901,6 @@ static SaAisErrorT admin_op_result_commo TRACE_1("Reactive ressurect of handle %llx succeeded", immOiHandle); } - if (cl_node->isApplier) { - rc = SA_AIS_ERR_BAD_HANDLE; - TRACE_2("ERR_BAD_HANDLE: The SaImmOiHandleT is associated with an >>applier<< name"); - goto stale_handle; - } - if(isA2bCall && !(cl_node->isImmA2b)) { rc = SA_AIS_ERR_VERSION; TRACE_2("ERR_VERSION: saImmOmAdminOperationInvoke_o2 only supported for " diff --git a/osaf/services/saf/immsv/README b/osaf/services/saf/immsv/README --- a/osaf/services/saf/immsv/README +++ b/osaf/services/saf/immsv/README @@ -1758,16 +1758,96 @@ incremental validation. This can be achi it then replaying the same operations (that validated), followed by adding more operations. Replay is necessary because the OIs ccb-protocol can only cope with one invocation of validation (completed callback) for any given -ccb-id. Another possible us is in integrating IMM transaction commit +ccb-id. Another possible use is in integrating IMM transaction commit with the commit of some other transaction handling system. By validating without committing, the risk is significantly reduced that a final commit/apply will fail. The invocation of saImmOmCcbApply after a -successfull invocation of saImmOmCcbValidate can still fail/abort +successfull invocation of saImmOmCcbValidate can still fail/abort, but only due to resource problems (such as server crash or filesystem unavailability). This is a blocking syncronous call. + +Allow admin-operations directly targeting an implementer or applier (4.5) +====================================================================== +https://sourceforge.net/p/opensaf/tickets/799/ + + +The existing IMM admin-operation API in OpenSAF: + + saImmOmAdminOperationInvoke_2() + saImmOmAdminOperationInvoke_o2() + saImmOmAdminOperationInvokeAsync_2() + SaImmOmAdminOperationInvokeCallbackT() + aImmOmAdminOperationInvokeCallbackT_o2() + + SaImmOiAdminOperationCallbackT_2() + saImmOiAdminOPerationResult() + saImmOiAdminOperationResult_o2() + +allows OM clients to invoke procedural requests directed at an imm object. +The OM client needs to have an admin-owner handle associated with an admin-owner +name that matches the admin-owner for the object. The actual target/receiver of +the admin-operation is really the implementer/OI registered for the object or +class. The object that anchors the request is effectively a parameter in the +request to the OI. + +This enhancement (#799) does not add any new API. It extends the allowed scope +for the existing admin-operation API to cover the case where the target is an OI +directly. Instead of supplying the DN of an object as the address/target, an +implementer-name is provided as the address/target. This allows the OM client to +invoke admin-operations directly and explicitly on an OI. The implementer-name +is used as a proxy for the object-name in the admin-operation API. + +Because the extended scope does not require the addition of any new API, access +to this extension is not based on the handle version used. But the enhancement +is introduced in OpenSAF release 4.5 and thus only available in that release or +later releases. + +The om-side admin-operation-invoke call takes an admin-owner-handle as argument. +The admin-owner handle needs to be an initialized handle and it must set the +admin-owner-name to be the *same* as the implementer-name. This may seem peculiar +and unnecessary. But it serves both as a confirmation that the OM client has not +made some mistake in using the new extended scope; and as a possible future +entry point for authorizing admin-operation access directly targeting the OI. + +The main benefit of this extension of scope, is that it allows a simple way for +applications to set up cluster scoped remote procedure call communication, where the +request arives FEVS-synchronously at the target. FEVS is the cluster synchronized +messaging mechanism used by the Immsv (see earlier in this README). + +The receiver process only needs to register as an implementer or applier with IMM. +In many cases the receiving process has done this anyway for other reasons. +The sender only needs to know the name of the implementer/applier, the operation-id +and expected arguments for the call. For this extended scope usage, the OI does not +necessarily need to be the real implementer/OI for *any* imm object at all. + +Another use case is that it allows an om-client to communicate with (or probe) an +OI/applier as such. An OI may be the OI for many objects and classes. In some cases, +requests for information, or requests for adjustments in behavior of the OI/applier +are generic and not associated with any specific object. For exaple, statistics or +resource utilization data, last processed ccb, for the OI or Applier. + +Appliers are only listeners/trackers of ccb changes. An applier is never reachable +via any *regular* admin-op invoked via some object. This since the applier will never +be *the* OI for any object. But this enhancement allows an OM client to communicate +directly also with appliers. This can for example be usefull if a main-OI needs +an applier to read the before-ccb-commit versions of objects being changed in a CCB. +The main OI can achieve this by sending a synchrnous admin-op to that applier from +inside the completed callback for the main OI. Because the main-OI has not returned +from the completed callback, the apply of that CCB is suspended waiting on the reply +on the completed callback. Once the applier has read the before-image data, from +inside the admin-op callback, it replies on the admin-op towards the main OI. The +main OI can then finish the validation and reply to the immsv. Note that the main OI +is in this example using both the OI and the OM API concurrently. + +One note of warning. Care needs to be taken when using *synchronous* admin-operations +not to create deadlock cycles between the involved processes. Any such deadlock will +be resolved by the timeout of the synchronous admin-ops, so the problem would be lack +of progress on some task, not a permanently hung set of processes. + + ---------------------------------------- DEPENDENCIES ============ diff --git a/osaf/services/saf/immsv/immnd/ImmModel.cc b/osaf/services/saf/immsv/immnd/ImmModel.cc --- a/osaf/services/saf/immsv/immnd/ImmModel.cc +++ b/osaf/services/saf/immsv/immnd/ImmModel.cc @@ -10067,6 +10067,7 @@ SaAisErrorT ImmModel::adminOperationInvo AdminOwnerInfo* adminOwner = 0; ObjectInfo* object = 0; + struct ObjectInfo dummyObject; /* Constructor zeroes members of stack allocated object */ ImplementerEvtMap::iterator iem; AdminOwnerVector::iterator i2; @@ -10112,6 +10113,18 @@ SaAisErrorT ImmModel::adminOperationInvo TRACE_7("Bouncing special preload admin-op"); err = SA_AIS_ERR_REPAIR_PENDING; } else { + dummyObject.mImplementer = findImplementer(objectName); + if(dummyObject.mImplementer) { + /* Appears to be an admin-op directed at OI. + Verify that admo-name matches impl-name. */ + if(objectName == adminOwner->mAdminOwnerName) { + object = &dummyObject; + goto fake_obj; + } + LOG_NO("ERR_NOT_EXIST: Admin-op on OI rejected. Implementer '%s' != adminowner '%s'", + objectName.c_str(), adminOwner->mAdminOwnerName.c_str()); + } + TRACE_7("ERR_NOT_EXIST: object '%s' does not exist", objectName.c_str()); err = SA_AIS_ERR_NOT_EXIST; } @@ -10136,6 +10149,7 @@ SaAisErrorT ImmModel::adminOperationInvo } } + fake_obj: // Check for call on object implementer if(object->mImplementer && object->mImplementer->mNodeId) { *implConn = object->mImplementer->mConn; diff --git a/osaf/tools/safimm/immadm/imm_admin.c b/osaf/tools/safimm/immadm/imm_admin.c --- a/osaf/tools/safimm/immadm/imm_admin.c +++ b/osaf/tools/safimm/immadm/imm_admin.c @@ -395,9 +395,14 @@ int main(int argc, char *argv[]) error = immutil_saImmOmAdminOwnerSet(ownerHandle, objectNames, SA_IMM_ONE); if (error != SA_AIS_OK) { - if (error == SA_AIS_ERR_NOT_EXIST) + if (error == SA_AIS_ERR_NOT_EXIST) { + if(strcmp(adminOwnerName, (const char *) objectName.value)==0) { + fprintf(stderr, "AdminOwnerName == ImplementerName (%s) - Could be direct admin-op on OI\n", adminOwnerName); + goto retry; + } fprintf(stderr, "error - saImmOmAdminOwnerSet - object '%s' does not exist\n", objectName.value); + } else fprintf(stderr, "error - saImmOmAdminOwnerSet FAILED: %s\n", saf_error(error)); exit(EXIT_FAILURE); diff --git a/tests/immsv/implementer/test_SaImmOiAdminOperation.c b/tests/immsv/implementer/test_SaImmOiAdminOperation.c --- a/tests/immsv/implementer/test_SaImmOiAdminOperation.c +++ b/tests/immsv/implementer/test_SaImmOiAdminOperation.c @@ -31,6 +31,9 @@ static SaAisErrorT immReturnValue; static SaAisErrorT operationReturnValue; static SaInvocationT userInvocation = 0xdead; +static SaBoolT useImplementerNameAsTarget = SA_FALSE; +static SaImmOiImplementerNameT implementerName = NULL;; + /* SaImmAdminOperationError */ static SaStringT adminOperationErrorString = NULL; static SaImmAdminOperationParamsT_2 adminOperationErrorParam = { @@ -179,7 +182,7 @@ static void *objectImplementerThreadMain { struct pollfd fds[1]; int ret; - const SaImmOiImplementerNameT implementerName = (SaImmOiImplementerNameT) __FUNCTION__; + implementerName = (SaImmOiImplementerNameT) __FUNCTION__; SaSelectionObjectT selObj; SaImmHandleT handle; const SaNameT *objectName = arg; @@ -223,23 +226,34 @@ static SaAisErrorT om_admin_exec(SaAisEr SaImmHandleT handle; SaImmAdminOwnerHandleT ownerHandle; const SaNameT *objectNames[] = {objectName, NULL}; + SaNameT localRdn = rdn; SaImmAdminOperationParamsT_2 param = { "TEST", SA_IMM_ATTR_SAUINT64T, &value }; const SaImmAdminOperationParamsT_2 *params[] = {¶m, NULL}; + SaImmAdminOwnerNameT admoName = adminOwnerName; if (in_rc == SA_AIS_ERR_INVALID_PARAM) param.paramType = -1; TRACE_ENTER(); safassert(saImmOmInitialize(&handle, NULL, &immVersion), SA_AIS_OK); - safassert(saImmOmAdminOwnerInitialize(handle, adminOwnerName, SA_TRUE, &ownerHandle), SA_AIS_OK); - safassert(saImmOmAdminOwnerSet(ownerHandle, objectNames, SA_IMM_SUBTREE), SA_AIS_OK); + if(useImplementerNameAsTarget) { + localRdn.length = strlen(implementerName); + assert(localRdn.length < 256); + strcpy((char *) localRdn.value, implementerName); + admoName = (char *) implementerName; + } + + safassert(saImmOmAdminOwnerInitialize(handle, admoName, SA_TRUE, &ownerHandle), SA_AIS_OK); + if(!useImplementerNameAsTarget) { + safassert(saImmOmAdminOwnerSet(ownerHandle, objectNames, SA_IMM_SUBTREE), SA_AIS_OK); + } *imm_rc = saImmOmAdminOperationInvoke_2( - ownerHandle, &rdn, 0, operationId, + ownerHandle, &localRdn, 0, operationId, params, &rc, SA_TIME_ONE_SECOND); saImmOmAdminOwnerFinalize(ownerHandle); /* Tend to get timeout here with PBE */ @@ -306,8 +320,9 @@ void SaImmOiAdminOperation_01(void) safassert(saImmOmCcbApply(ccbHandle), SA_AIS_OK); safassert(saImmOmCcbFinalize(ccbHandle), SA_AIS_OK); safassert(saImmOmFinalize(immOmHandle), SA_AIS_OK); + useImplementerNameAsTarget = SA_FALSE; - assert(imm_rc == SA_AIS_OK); + if(imm_rc != SA_AIS_OK) {rc = imm_rc;} test_validate(rc, SA_AIS_OK); TRACE_LEAVE(); } @@ -1033,6 +1048,14 @@ done: TRACE_LEAVE(); } + +void SaImmOiAdminOperation_13(void) +{ + useImplementerNameAsTarget = SA_TRUE; + SaImmOiAdminOperation_01(); +} + + __attribute__ ((constructor)) static void saImmOiInitialize_2_constructor(void) { test_suite_add(5, "Administrative Operations"); @@ -1048,5 +1071,6 @@ done: test_case_add(5, SaImmOiAdminOperation_10, "SaImmOiAdminOperation - SA_AIS_ERR_BAD_OPERATION, SaImmAdminOperationName"); test_case_add(5, SaImmOiAdminOperation_11, "SaImmOiAdminOperation - SA_AIS_OK, SaImmAdminOperationName (first param) - async"); test_case_add(5, SaImmOiAdminOperation_12, "SaImmOiAdminOperation - SA_AIS_OK, SaImmAdminOperationName (first param) - sync"); + test_case_add(5, SaImmOiAdminOperation_13, "SaImmOiAdminOperation - SA_AIS_OK, Same as 5 1 but with implementername as target"); } ------------------------------------------------------------------------------ "Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE Instantly run your Selenium tests across 300+ browser/OS combos. Get unparalleled scalability from the best Selenium testing platform available. Simple to use. Nothing to install. Get started now for free." http://p.sf.net/sfu/SauceLabs _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel