osaf/libs/common/amf/include/amf_defs.h | 6 + osaf/services/saf/amf/amfnd/Makefile.am | 1 + osaf/services/saf/amf/amfnd/evt.cc | 7 + osaf/services/saf/amf/amfnd/hcdb.cc | 150 ++++ osaf/services/saf/amf/amfnd/imm.cc | 758 ++++++++++++++++++++++++ osaf/services/saf/amf/amfnd/include/Makefile.am | 1 + osaf/services/saf/amf/amfnd/include/avnd.h | 1 + osaf/services/saf/amf/amfnd/include/avnd_evt.h | 8 + osaf/services/saf/amf/amfnd/include/avnd_hc.h | 1 + osaf/services/saf/amf/amfnd/include/avnd_imm.h | 148 ++++ osaf/services/saf/amf/amfnd/main.cc | 10 +- 11 files changed, 1090 insertions(+), 1 deletions(-)
This first patch adds support for changing attributes in class SaAmfHealthcheckType Updated with review comments. diff --git a/osaf/libs/common/amf/include/amf_defs.h b/osaf/libs/common/amf/include/amf_defs.h --- a/osaf/libs/common/amf/include/amf_defs.h +++ b/osaf/libs/common/amf/include/amf_defs.h @@ -254,6 +254,12 @@ typedef enum saAmfHealthcheckMaxDuration_ID = 2, } AVSV_AMF_HEALTHCHECK_ATTR_ID; +/* Attribute ID enum for the SaAmfHealthcheckType class */ +typedef enum +{ + saAmfHctDefPeriod_ID = 1, + saAmfHctDefMaxDuration_ID = 2, +} AMF_HEALTHCHECK_TYPE_ATTR_ID; #define AVSV_COMMON_SUB_ID_DEFAULT_VAL 1 #define SA_AMF_PRESENCE_ORPHANED (SA_AMF_PRESENCE_TERMINATION_FAILED+1) diff --git a/osaf/services/saf/amf/amfnd/Makefile.am b/osaf/services/saf/amf/amfnd/Makefile.am --- a/osaf/services/saf/amf/amfnd/Makefile.am +++ b/osaf/services/saf/amf/amfnd/Makefile.am @@ -51,6 +51,7 @@ osafamfnd_SOURCES = \ err.cc \ evt.cc \ hcdb.cc \ + imm.cc \ main.cc \ mbcsv.cc \ mds.cc \ diff --git a/osaf/services/saf/amf/amfnd/evt.cc b/osaf/services/saf/amf/amfnd/evt.cc --- a/osaf/services/saf/amf/amfnd/evt.cc +++ b/osaf/services/saf/amf/amfnd/evt.cc @@ -32,6 +32,7 @@ */ #include "avnd.h" +#include "avnd_imm.h" /**************************************************************************** Name : avnd_evt_create @@ -200,6 +201,7 @@ AVND_EVT *avnd_evt_create(AVND_CB *cb, void avnd_evt_destroy(AVND_EVT *evt) { uint32_t type = 0; + AvndImmEvt *imm = 0; if (!evt) return; @@ -294,6 +296,11 @@ void avnd_evt_destroy(AVND_EVT *evt) case AVND_EVT_PID_EXIT: break; + case AVND_EVT_IMM: + imm = static_cast<AvndImmEvt*>(evt->info.imm.imm_evt); + delete imm; + break; + default: LOG_NO("%s: unknown event type %u", __FUNCTION__, type); break; diff --git a/osaf/services/saf/amf/amfnd/hcdb.cc b/osaf/services/saf/amf/amfnd/hcdb.cc --- a/osaf/services/saf/amf/amfnd/hcdb.cc +++ b/osaf/services/saf/amf/amfnd/hcdb.cc @@ -36,6 +36,7 @@ #include "avnd.h" #include <saImmOm.h> #include <immutil.h> +#include <string> static NCS_PATRICIA_TREE hctypedb; /* healthcheck type db */ @@ -339,6 +340,93 @@ SaAisErrorT avnd_hctype_config_get(SaImm return error; } +// Search for a given key and return its value or empty string if not found. +static std::string search_key(const std::string& str, const std::string& key) +{ + std::string value; + + std::string::size_type idx1; + + idx1 = str.find(key); + + // if key was found + if (idx1 != std::string::npos) { + // get value, idx2 points to value + idx1 += key.length(); + std::string part2 = str.substr(idx1); + + idx1 = part2.find(","); + + // get value + value = part2.substr(0, idx1); + } + + return value; +} + +// +static void comp_hctype_update_compdb(AVND_CB *cb, AVSV_PARAM_INFO *param) +{ + AVND_COMP_HC_REC *comp_hc_rec; + AVND_COMP * comp; + char *comp_type_name; + AVSV_HLT_KEY hlt_chk; + AVND_COMP_HC_REC tmp_hc_rec; + + // 1. find component from componentType, + // input example, param->name.value = safHealthcheckKey=AmfDemo,safVersion=1,safCompType=AmfDemo1 + comp_type_name = strstr((char *) param->name.value, "safVersion"); + TRACE("comp_type_name: %s", comp_type_name); + osafassert(comp_type_name); + + // 2. search each component for a matching compType + comp = (AVND_COMP *) ncs_patricia_tree_getnext(&cb->compdb, (uint8_t *) 0); + while (comp != 0) { + if (strncmp((const char*) comp->saAmfCompType.value, comp_type_name, comp->saAmfCompType.length) == 0) { + + // 3. matching compType found, check that component does not have a SaAmfHealthcheck rec (specialization) + std::string hlt_chk_key = search_key((const char*) param->name.value, "safHealthcheckKey="); + if (hlt_chk_key.empty()) { + LOG_ER("%s: failed to get healthcheckKey from %s", __FUNCTION__, param->name.value); + return; + } + + memset(&hlt_chk, 0, sizeof(AVSV_HLT_KEY)); + hlt_chk.comp_name.length = comp->name.length; + memcpy(hlt_chk.comp_name.value, comp->name.value, hlt_chk.comp_name.length); + hlt_chk.key_len = hlt_chk_key.size(); + memcpy(hlt_chk.name.key, hlt_chk_key.c_str(), hlt_chk_key.size()); + hlt_chk.name.keyLen = hlt_chk.key_len; + TRACE("comp_name %s key %s keyLen %u", hlt_chk.comp_name.value, hlt_chk.name.key, hlt_chk.name.keyLen); + if (avnd_hcdb_rec_get(cb, &hlt_chk) == 0) { + TRACE("comp uses healthcheckType rec"); + // 4. found a component that uses the healthcheckType record, update the comp_hc_rec + memset(&tmp_hc_rec, '\0', sizeof(AVND_COMP_HC_REC)); + tmp_hc_rec.key = hlt_chk.name; + tmp_hc_rec.req_hdl = comp->reg_hdl; + TRACE("tmp_hc_rec: key %s req_hdl %llu", tmp_hc_rec.key.key, tmp_hc_rec.req_hdl); + if ((comp_hc_rec = m_AVND_COMPDB_REC_HC_GET(*comp, tmp_hc_rec)) != 0) { + TRACE("comp_hc_rec: period %llu max_dur %llu", comp_hc_rec->period, comp_hc_rec->max_dur); + switch (param->attr_id) { + case saAmfHctDefPeriod_ID: + comp_hc_rec->period = *((SaTimeT *) param->value); + LOG_NO("%s: saAmfHctDefPeriod updated, new value: %" PRIu64, __FUNCTION__, (uint64_t) comp_hc_rec->period); + break; + case saAmfHctDefMaxDuration_ID: + comp_hc_rec->max_dur = *((SaTimeT *) param->value); + LOG_NO("%s: saAmfHctDefMaxDuration updated, new value: %" PRIu64, __FUNCTION__, (uint64_t) comp_hc_rec->max_dur); + break; + default: + osafassert(0); + } + } + } + } + comp = (AVND_COMP *) ncs_patricia_tree_getnext(&cb->compdb, (uint8_t *) & comp->name); + } +} + +// uint32_t avnd_hc_oper_req(AVND_CB *cb, AVSV_PARAM_INFO *param) { uint32_t rc = NCSCC_RC_FAILURE; @@ -401,3 +489,65 @@ done: return rc; } +uint32_t avnd_hctype_oper_req(AVND_CB *cb, AVSV_PARAM_INFO *param) +{ + uint32_t rc = NCSCC_RC_FAILURE; + + TRACE_ENTER2("'%s'", param->name.value); + AVND_HCTYPE *hctype = (AVND_HCTYPE *) ncs_patricia_tree_get(&hctypedb, (uint8_t *)¶m->name); + + switch (param->act) { + case AVSV_OBJ_OPR_MOD: { + if (!hctype) { + LOG_ER("%s: failed to get %s", __FUNCTION__, param->name.value); + goto done; + } + + switch (param->attr_id) { + case saAmfHctDefPeriod_ID: + osafassert(sizeof(SaTimeT) == param->value_len); + hctype->saAmfHctDefPeriod = *((SaTimeT *)param->value); + comp_hctype_update_compdb(cb, param); + break; + + case saAmfHctDefMaxDuration_ID: + osafassert(sizeof(SaTimeT) == param->value_len); + hctype->saAmfHctDefMaxDuration = *((SaTimeT *)param->value); + comp_hctype_update_compdb(cb, param); + break; + + default: + LOG_NO("%s: Unsupported attribute %u", __FUNCTION__, param->attr_id); + goto done; + } + break; + } + + case AVSV_OBJ_OPR_DEL: { + if (hctype != NULL) { + rc = ncs_patricia_tree_del(&hctypedb, &hctype->tree_node); + osafassert(rc == NCSCC_RC_SUCCESS); + LOG_IN("Deleted '%s'", param->name.value); + } else { + /* + ** Normal case that happens if a parent of this HC was + ** the real delete target for the CCB. + */ + TRACE("already deleted!"); + } + + break; + } + default: + LOG_NO("%s: Unsupported action %u", __FUNCTION__, param->act); + goto done; + } + + rc = NCSCC_RC_SUCCESS; + +done: + rc = NCSCC_RC_SUCCESS; + + TRACE_LEAVE(); + return rc; +} diff --git a/osaf/services/saf/amf/amfnd/imm.cc b/osaf/services/saf/amf/amfnd/imm.cc new file mode 100644 --- /dev/null +++ b/osaf/services/saf/amf/amfnd/imm.cc @@ -0,0 +1,758 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2014 The OpenSAF Foundation + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Author(s): Ericsson AB + * + */ + +/***************************************************************************** + + DESCRIPTION: + + ****************************************************************************/ +#include <string> +#include <cstring> +#include <algorithm> +#include <poll.h> +#include "avnd_imm.h" +#include "immutil.h" + +extern struct ImmutilWrapperProfile immutilWrapperProfile; + +// +SaVersionT AvndImm::immVersion_ = {'A', 2, 11}; +SaImmOiHandleT AvndImm::immOiHandle_ = 0; +SaImmOiHandleT AvndImm::immOmHandle_ = 0; +SaSelectionObjectT AvndImm::imm_sel_obj_ = -1; +AvndImm::UpdateFn AvndImm::update_callback_[AVSV_SA_AMF_CLASS_MAX] = {0}; + +// This string array must match the AVND_AMF_CLASS_ID enum +const char *AvndImm::avnd_class_names_[] = { + "SaAmfHealthcheckType" +}; + +/** + * This method adds IMM modification attribute to attribute vector + * + * @param attr + */ +void AvndImmEvt::set_mod_attr(const SaImmAttrModificationT_2& attr) { + SaImmAttrModificationT_2 *tmp = new SaImmAttrModificationT_2; + tmp->modType = attr.modType; + AvndImmUtil::copySaImmAttrValuesT(tmp->modAttr, attr.modAttr); + attr_.push_back(tmp); +} + + +/** + * Destructor + */ +AvndImmEvt::~AvndImmEvt() { + std::for_each(attr_.begin(), attr_.end(), AvndImmUtil::remove_attr); + attr_.clear(); +} + +/** + * This function returns a pointer to a new string which is a duplicate of the string s. + * + * @param s + * + * @return pointer to new string + */ +char *AvndImmUtil::str_dup(const char *s) { + char *c = new char[strlen(s) + 1]; + std::strcpy(c, s); + return c; +} + +/** + * This function returns the size of given attribute value type. + * + * @param attrValueType + * + * @return attrValueType size + */ +size_t AvndImmUtil::value_size(SaImmValueTypeT attrValueType) { + size_t value_size = 0; + + switch (attrValueType) { + case SA_IMM_ATTR_SAINT32T: + value_size = sizeof(SaInt32T); + break; + case SA_IMM_ATTR_SAUINT32T: + value_size = sizeof(SaUint32T); + break; + case SA_IMM_ATTR_SAINT64T: + value_size = sizeof(SaInt64T); + break; + case SA_IMM_ATTR_SAUINT64T: + value_size = sizeof(SaUint64T); + break; + case SA_IMM_ATTR_SATIMET: + value_size = sizeof(SaTimeT); + break; + case SA_IMM_ATTR_SANAMET: + value_size = sizeof(SaNameT); + break; + case SA_IMM_ATTR_SAFLOATT: + value_size = sizeof(SaFloatT); + break; + case SA_IMM_ATTR_SADOUBLET: + value_size = sizeof(SaDoubleT); + break; + case SA_IMM_ATTR_SASTRINGT: + value_size = sizeof(SaStringT); + break; + case SA_IMM_ATTR_SAANYT: + osafassert(0); + break; + } + + return value_size; +} + +/** + * This function returns class enum corresponding to object name. + * + * @param obj_name + * @param class_type + * + * @return AVSV_AMF_CLASS_ID + */ +AVSV_AMF_CLASS_ID AvndImmUtil::object_name_to_class_type(const SaNameT *obj_name) { + AVSV_AMF_CLASS_ID class_type = AVSV_SA_AMF_CLASS_INVALID; + + /* Cluster and Node Class Related */ + if (strncmp((char *)&obj_name->value, "safAmfCluster=", 14) == 0) { + class_type = AVSV_SA_AMF_CLUSTER; + } else if (strncmp((char *)&obj_name->value, "safAmfNode=", 11) == 0) { + class_type = AVSV_SA_AMF_NODE; + } else if (strncmp((char *)&obj_name->value, "safAmfNodeGroup=", 16) == 0) { + class_type = AVSV_SA_AMF_NODE_GROUP; + } else if (strncmp((char *)&obj_name->value, "safInstalledSwBundle=", 21) == 0) { + class_type = AVSV_SA_AMF_NODE_SW_BUNDLE; + } + + /* Application Class Related */ + else if (strncmp((char *)&obj_name->value, "safApp=", 7) == 0) { + class_type = AVSV_SA_AMF_APP; + } else if (strncmp((char *)&obj_name->value, "safAppType=", 11) == 0) { + class_type = AVSV_SA_AMF_APP_BASE_TYPE; + } + + /* Service Group Class Related */ + else if (strncmp((char *)&obj_name->value, "safSg=", 6) == 0) { + class_type = AVSV_SA_AMF_SG; + } else if (strncmp((char *)&obj_name->value, "safSgType=", 10) == 0) { + class_type = AVSV_SA_AMF_SG_BASE_TYPE; + } + + /* Service Unit Class Related */ + else if (strncmp((char *)&obj_name->value, "safSu=", 6) == 0) { + class_type = AVSV_SA_AMF_SU; + } else if (strncmp((char *)&obj_name->value, "safSuType=", 10) == 0) { + class_type = AVSV_SA_AMF_SU_BASE_TYPE; + } else if (strncmp((char *)&obj_name->value, "safMemberCompType=", 18) == 0) { + class_type = AVSV_SA_AMF_SUT_COMP_TYPE; + } + + /* Service Instance Class Related */ + else if (strncmp((char *)&obj_name->value, "safSi=", 6) == 0) { + class_type = AVSV_SA_AMF_SI; + } else if (strncmp((char *)&obj_name->value, "safSvcType=", 11) == 0) { + class_type = AVSV_SA_AMF_SVC_BASE_TYPE; + } else if (strncmp((char *)&obj_name->value, "safDepend=", 10) == 0) { + class_type = AVSV_SA_AMF_SI_DEPENDENCY; + } else if (strncmp((char *)&obj_name->value, "safRankedSu=", 12) == 0) { + class_type = AVSV_SA_AMF_SI_RANKED_SU; + } else if (strncmp((char *)&obj_name->value, "safSISU=", 8) == 0) { + class_type = AVSV_SA_AMF_SI_ASSIGNMENT; + } else if (strncmp((char *)&obj_name->value, "safMemberCSType=", 16) == 0) { + class_type = AVSV_SA_AMF_SVC_TYPE_CS_TYPES; + } + + /* Component Service Instance Class Related */ + else if (strncmp((char *)&obj_name->value, "safCsi=", 7) == 0) { + class_type = AVSV_SA_AMF_CSI; + } else if (strncmp((char *)&obj_name->value, "safCSType=", 10) == 0) { + class_type = AVSV_SA_AMF_CS_BASE_TYPE; + } else if (strncmp((char *)&obj_name->value, "safCsiAttr=", 11) == 0) { + class_type = AVSV_SA_AMF_CSI_ATTRIBUTE; + } else if (strncmp((char *)&obj_name->value, "safCSIComp=", 11) == 0) { + class_type = AVSV_SA_AMF_CSI_ASSIGNMENT; + } + + /* Component and component types Related */ + else if (strncmp((char *)&obj_name->value, "safCompType=", 12) == 0) { + class_type = AVSV_SA_AMF_COMP_BASE_TYPE; + } else if (strncmp((char *)&obj_name->value, "safSupportedCsType=", 19) == 0) { + if (strstr((char *)&obj_name->value, "safCompType=") != 0) { + class_type = AVSV_SA_AMF_CT_CS_TYPE; + } else if (strstr((char *)&obj_name->value, "safComp=") != 0) { + class_type = AVSV_SA_AMF_COMP_CS_TYPE; + } + } else if (strncmp((char *)&obj_name->value, "safComp=", 8) == 0) { + class_type = AVSV_SA_AMF_COMP; + } + + /* Global Component Attributes and Health Check Related */ + else if (strncmp((char *)&obj_name->value, "safRdn=", 7) == 0) { + class_type = AVSV_SA_AMF_COMP_GLOBAL_ATTR; + } else if (strncmp((char *)&obj_name->value, "safHealthcheckKey=", 18) == 0) { + if (strstr((char *)&obj_name->value, "safVersion=") != 0) { + class_type = AVSV_SA_AMF_HEALTH_CHECK_TYPE; + } else if (strstr((char *)&obj_name->value, "safComp=") != 0) { + class_type = AVSV_SA_AMF_HEALTH_CHECK; + } + } + + /* Common Version Related */ + else if (strncmp((char *)&obj_name->value, "safVersion=", 11) == 0) { + if (strstr((char *)&obj_name->value, "safAppType=") != 0) { + class_type = AVSV_SA_AMF_APP_TYPE; + } else if (strstr((char *)&obj_name->value, "safSgType=") != 0) { + class_type = AVSV_SA_AMF_SG_TYPE; + } else if (strstr((char *)&obj_name->value, "safSuType=") != 0) { + class_type = AVSV_SA_AMF_SU_TYPE; + } else if (strstr((char *)&obj_name->value, "safSvcType=") != 0) { + class_type = AVSV_SA_AMF_SVC_TYPE; + } else if (strstr((char *)&obj_name->value, "safCSType=") != 0) { + class_type = AVSV_SA_AMF_CS_TYPE; + } else if (strstr((char *)&obj_name->value, "safCompType=") != 0) { + class_type = AVSV_SA_AMF_COMP_TYPE; + } + } + + return class_type; +} + +/** + * Delete attribute structures. + * + * @param attr + */ +void AvndImmUtil::remove_attr(SaImmAttrModificationT_2* attr) { + AvndImmUtil::deleteSaImmAttrValuesT(attr->modAttr); + delete attr; +} + +/** + * Delete attribute values. + * + * @param reference to attrValue + */ +void AvndImmUtil::deleteSaImmAttrValuesT(SaImmAttrValuesT_2& attr_value) { + unsigned int i; + + if (attr_value.attrValueType == SA_IMM_ATTR_SASTRINGT) { + for (i = 0; i < attr_value.attrValuesNumber; i++) { + char *p = *((char**) attr_value.attrValues[i]); + delete [] p; + } + } + + delete [] attr_value.attrName; + delete [] static_cast<char*> (attr_value.attrValues[0]); // free blob shared by all values + delete [] attr_value.attrValues; + +} + +/** + * Copy IMM attr values, + * + * @param to + * @param from + */ +void AvndImmUtil::copySaImmAttrValuesT(SaImmAttrValuesT_2& to, const SaImmAttrValuesT_2& from) { + size_t val_size = 0; + unsigned int i; + unsigned int value_count = from.attrValuesNumber; + char *databuffer; + + to.attrName = str_dup(from.attrName); + + to.attrValuesNumber = value_count; + to.attrValueType = from.attrValueType; + if (value_count == 0) + return; /* (just in case...) */ + + to.attrValues = new SaImmAttrValueT[value_count]; + + val_size = value_size(from.attrValueType); + + // alloc blob shared by all values + databuffer = new char[value_count * val_size]; + + for (i = 0; i < value_count; i++) { + to.attrValues[i] = databuffer; + if (from.attrValueType == SA_IMM_ATTR_SASTRINGT) { + char *cporig = *((char **) from.attrValues[i]); + char **cpp = (char **) databuffer; + *cpp = str_dup(cporig); + } else { + memcpy(databuffer, from.attrValues[i], val_size); + } + databuffer += val_size; + } +} + +/** + * Function called for not implemented callback types. + * + * @param object_name + * @param imm_attr + * + * @return NCSCC_RC_FAILURE; + */ +uint32_t AvndImm::not_yet_implemented(const std::string& object_name, const SaImmAttrModificationT_2* imm_attr) { + LOG_WA("Not yet implemented"); + return NCSCC_RC_FAILURE; +} + +/** + * Function called for updating health check type. + * + * @param object_name + * @param imm_attr + * + * @return NCSCC_RC_SUCCESS or NCSCC_RC_FAILURE; + */ +uint32_t AvndImm::update_health_check_type(const std::string& object_name, const SaImmAttrModificationT_2* imm_attr) { + uint32_t rc = NCSCC_RC_FAILURE; + AVND_CB *cb = avnd_cb; + + AVSV_PARAM_INFO param; + memset(¶m, 0, sizeof(param)); + param.class_id = AVSV_SA_AMF_HEALTH_CHECK_TYPE; + + std::string attr_name = imm_attr->modAttr.attrName; + + strncpy((char*) param.name.value, object_name.c_str(), object_name.size()); + param.name.length = object_name.size(); + + if (attr_name == "saAmfHctDefPeriod") { + param.attr_id = saAmfHctDefPeriod_ID; + } else if (attr_name == "saAmfHctDefMaxDuration") { + param.attr_id = saAmfHctDefMaxDuration_ID; + } else { + LOG_WA("Unknown attribute name %s", attr_name.c_str()); + rc = NCSCC_RC_FAILURE; + goto done; + } + + if (imm_attr->modType == SA_IMM_ATTR_VALUES_REPLACE) { + param.act = AVSV_OBJ_OPR_MOD; + } else if (imm_attr->modType == SA_IMM_ATTR_VALUES_DELETE) { + param.act = AVSV_OBJ_OPR_DEL; + } else { + LOG_WA("Unknown modificaton type %d", imm_attr->modType); + rc = NCSCC_RC_FAILURE; + goto done; + } + + param.value_len = AvndImmUtil::value_size(imm_attr->modAttr.attrValueType); + memcpy(param.value, *imm_attr->modAttr.attrValues, param.value_len); + + rc = avnd_hctype_oper_req(cb, ¶m); + +done: + return rc; +} + +/** + * IMM event handle, dispatch callback function for each changed attribute in the current event. + * + * @param cb + * @param evt + * + * @return NCSCC_RC_SUCCESS or NCSCC_RC_FAILURE + */ +uint32_t avnd_evt_imm_evh(AVND_CB *cb, AVND_EVT *evt) { + AVSV_AMF_CLASS_ID type; + uint32_t rc = NCSCC_RC_FAILURE; + + TRACE_ENTER(); + + AvndImmEvt *imm_evt = (AvndImmEvt*) evt->info.imm.imm_evt; + + // TODO(uabhano) change object_name_to_class_type argument to std::string, then the SaNameT code below can be removed + SaNameT obj_name; + obj_name.length = imm_evt->get_object_name().size(); + memcpy((char*)obj_name.value, imm_evt->get_object_name().c_str(), obj_name.length); + type = AvndImmUtil::object_name_to_class_type(&obj_name); + + for (std::vector<SaImmAttrModificationT_2*>::const_iterator it = imm_evt->begin(); it != imm_evt->end(); ++it) { + const SaImmAttrModificationT_2 *imm_attr = *it; + rc = AvndImm::update_callback_[type](imm_evt->get_object_name(), imm_attr); + } + + TRACE_LEAVE(); + return rc; +} + +/** + * Handle imm apply, create and send an AvndImmEvt object to the avnd main thread. + * + * @param immoi_handle + * @param ccb_id + */ +void AvndImm::ccb_apply_cb(SaImmOiHandleT immoi_handle, SaImmOiCcbIdT ccb_id) { + AVND_EVT_TYPE type = AVND_EVT_IMM; + + AVND_EVT *evt = 0; + const SaImmAttrModificationT_2 *mod; + int i = 0; + CcbUtilCcbData_t *ccb_util_ccb_data; + CcbUtilOperationData_t *opdata = NULL; + AvndImmEvt *imm_evt; + uint32_t rc = NCSCC_RC_SUCCESS; + AVND_CB *cb = avnd_cb; + + TRACE_ENTER2("CCB ID %llu", ccb_id); + + while ((opdata = ccbutil_getNextCcbOp(ccb_id, opdata)) != NULL) { + imm_evt = new AvndImmEvt(opdata->objectName); + while ((mod = opdata->param.modify.attrMods[i++]) != NULL) { + imm_evt->set_mod_attr(*mod); + } + + i = 0; + + /* create and send an event */ + + evt = new AVND_EVT(); + + evt->type = type; + evt->priority = NCS_IPC_PRIORITY_NORMAL; + evt->info.imm.imm_evt = imm_evt; + + rc = m_NCS_IPC_SEND(&cb->mbx, evt, evt->priority); + if (rc != NCSCC_RC_SUCCESS) { + LOG_CR("AvND send event to mailbox failed, type = %u", evt->type); + } + } + + /* Return CCB container memory */ + ccb_util_ccb_data = ccbutil_findCcbData(ccb_id); + osafassert(ccb_util_ccb_data); + ccbutil_deleteCcbData(ccb_util_ccb_data); + + TRACE_LEAVE(); +} + +/** + * IMM modify callback, memorize the request. + * + * @param immoi_handle + * @param ccb_id + * @param object_name + * @param attr_mods + * + * @return SA_AIS_OK or or SA_AIS_ERR_xx + */ +SaAisErrorT AvndImm::ccb_object_modify_cb(SaImmOiHandleT immoi_handle, + SaImmOiCcbIdT ccb_id, const SaNameT *object_name, + const SaImmAttrModificationT_2 **attr_mods) { + SaAisErrorT rc = SA_AIS_OK; + struct CcbUtilCcbData *ccb_util_ccb_data; + + TRACE_ENTER2("CCB ID %llu, %s", ccb_id, object_name->value); + + if ((ccb_util_ccb_data = ccbutil_getCcbData(ccb_id)) != NULL) { + /* "memorize the request" */ + if (ccbutil_ccbAddModifyOperation(ccb_util_ccb_data, object_name, attr_mods) != 0) { + LOG_ER("Failed '%s'", object_name->value); + rc = SA_AIS_ERR_BAD_OPERATION; + } + } else { + LOG_ER("Failed to get CCB object for %llu", ccb_id); + rc = SA_AIS_ERR_NO_MEMORY; + } + + TRACE_LEAVE(); + + return rc; +} + +/** + * IMM ccb abort callback. + * + * @param immoi_handle + * @param ccb_id + */ +void AvndImm::ccb_abort_cb(SaImmOiHandleT immoi_handle, SaImmOiCcbIdT ccb_id) { + TRACE_ENTER(); + + CcbUtilCcbData_t *ccb_util_ccb_data; + + /* Return CCB container memory */ + ccb_util_ccb_data = ccbutil_findCcbData(ccb_id); + osafassert(ccb_util_ccb_data); + ccbutil_deleteCcbData(ccb_util_ccb_data); + + TRACE_LEAVE(); +} + +/** + * IMM ccb object delete callback. + * + * @param immoi_handle + * @param ccb_id, + * @param object_name + * + * @return SA_AIS_OK + */ +SaAisErrorT AvndImm::ccb_object_delete_cb(SaImmOiHandleT immoi_handle, + SaImmOiCcbIdT ccb_id, const SaNameT *object_name) { + + TRACE_ENTER(); + TRACE_LEAVE(); + + return SA_AIS_OK; +} + +/** + * IMM ccb completed callback. + * + * @param immoi_handle + * @param ccb_id, + * + * @return SA_AIS_OK + */ +SaAisErrorT AvndImm::ccb_completed_cb(SaImmOiHandleT immoi_handle, + SaImmOiCcbIdT ccb_id) { + + TRACE_ENTER(); + TRACE_LEAVE(); + + return SA_AIS_OK; +} + +/** + * IMM ccb object create callback. + * + * @param immoi_handle + * @param ccb_id + * @param class_name + * @param parent_name + * @param attr + * + * @return SA_AIS_OK + */ +SaAisErrorT AvndImm::ccb_object_create_cb(SaImmOiHandleT immoi_handle, + SaImmOiCcbIdT ccb_id, const SaImmClassNameT class_name, + const SaNameT *parent_name, const SaImmAttrValuesT_2 **attr) { + + TRACE_ENTER(); + TRACE_LEAVE(); + + return SA_AIS_OK; +} + +const SaImmOiCallbacksT_2 AvndImm::avnd_callbacks_ = { + .saImmOiAdminOperationCallback = NULL, + .saImmOiCcbAbortCallback = ccb_abort_cb, + .saImmOiCcbApplyCallback = ccb_apply_cb, + .saImmOiCcbCompletedCallback = ccb_completed_cb, + .saImmOiCcbObjectCreateCallback = ccb_object_create_cb, + .saImmOiCcbObjectDeleteCallback = ccb_object_delete_cb, + .saImmOiCcbObjectModifyCallback = ccb_object_modify_cb, + .saImmOiRtAttrUpdateCallback = NULL +}; + +/** + * Set IMM applier. + * + * @return SA_AIS_OK or or SA_AIS_ERR_xx + */ +SaAisErrorT AvndImm::imm_applier_set() { + SaAisErrorT rc = SA_AIS_OK; + uint32_t i; + std::string applier_name = "@safAmfNodeDirector_"; + + TRACE_ENTER(); + + char hostname[_POSIX_HOST_NAME_MAX]; + if (gethostname(hostname, _POSIX_HOST_NAME_MAX) == -1) { + LOG_ER("gethostname failed: %s\n", strerror(errno)); + + /* use the node id of the node on which the AVD is running instead. */ + SaClmNodeIdT node_id_avnd = m_NCS_GET_NODE_ID; + snprintf(hostname, _POSIX_HOST_NAME_MAX, "%x", node_id_avnd); + } + + applier_name += hostname; + + LOG_NO("IMM applier name: %s", applier_name.c_str()); + + // + if ((rc = immutil_saImmOiImplementerSet(immOiHandle_, (char*) applier_name.c_str())) != SA_AIS_OK) { + LOG_ER("saImmOiImplementerSet failed %u", rc); + return rc; + } + + // + for (i = 0; i < AVND_SA_AMF_CLASS_MAX; i++) { + if ((rc = immutil_saImmOiClassImplementerSet(immOiHandle_, avnd_class_names_[i])) != SA_AIS_OK) { + LOG_ER("Impl Set Failed for %s, returned %d", avnd_class_names_[i], rc); + break; + } + } + + TRACE_LEAVE(); + + return rc; +} + +/** + * Initialize IMM. + * + * @return SA_AIS_OK or or SA_AIS_ERR_xx + */ +SaAisErrorT AvndImm::imm_init() { + SaAisErrorT rc = SA_AIS_OK ; + + TRACE_ENTER(); + + for (int i = 0; i < AVSV_SA_AMF_CLASS_MAX; ++i) { + update_callback_[i] = not_yet_implemented; + } + + update_callback_[AVSV_SA_AMF_HEALTH_CHECK_TYPE] = update_health_check_type; + + /* Setup immutils profile once and for all */ + immutilWrapperProfile.errorsAreFatal = false; + immutilWrapperProfile.retryInterval = 1000; + immutilWrapperProfile.nTries = 180; + + if ((rc = immutil_saImmOiInitialize_2(&immOiHandle_, &avnd_callbacks_, &immVersion_)) != SA_AIS_OK) { + LOG_ER("saImmOiInitialize failed %u", rc); + goto done; + } + + if ((rc = immutil_saImmOmInitialize(&immOmHandle_, NULL, &immVersion_)) != SA_AIS_OK) { + LOG_ER("saImmOmInitialize failed %u", rc); + goto done; + } + + if ((rc = immutil_saImmOiSelectionObjectGet(immOiHandle_, &imm_sel_obj_)) != SA_AIS_OK) { + LOG_ER("saImmOiSelectionObjectGet failed %u", rc); + goto done; + } + + TRACE("Successfully initialized IMM"); + +done: + TRACE_LEAVE(); + + return rc; +} + +/** + * IMM thread main function, waits for IMM events and dispatch callback functions. + */ +void AvndImm::imm_main() { + SaAisErrorT rc = SA_AIS_OK; + + enum { + FD_IMM = 0 + }; + + static nfds_t nfds = FD_IMM + 1; + int polltmo = -1; + static struct pollfd fds[FD_IMM + 1]; + + TRACE_ENTER(); + + fds[FD_IMM].fd = imm_sel_obj_; + fds[FD_IMM].events = POLLIN; + nfds = FD_IMM + 1; + + while (true) { + int pollretval = poll(fds, nfds, polltmo); + + if (pollretval == -1) { + if (errno == EINTR) + continue; + + LOG_ER("main: poll FAILED - %s", strerror(errno)); + break; + } + + if (immOiHandle_ && fds[FD_IMM].revents & POLLIN) { + TRACE("IMM event rec"); + rc = saImmOiDispatch(immOiHandle_, SA_DISPATCH_ALL); + if (rc != SA_AIS_OK) { + LOG_ER("saImmOiDispatch failed: %d", rc); + + } + } + } + + TRACE_LEAVE(); +} + +/** + * IMM thread start function. Init IMM and set as applier. + * + * @return 0 + */ +void *AvndImm::imm_start(void *) { + SaAisErrorT rc = SA_AIS_OK; + + TRACE_ENTER(); + + if ((rc = imm_init()) != SA_AIS_OK) { + LOG_ER("avnd_imm_init FAILED"); + goto done; + } + + if ((rc = imm_applier_set()) != SA_AIS_OK) { + LOG_ER("avnd_imm_applier set FAILED"); + goto done; + } + + imm_main(); + +done: + + return 0; +} + +/** + * Create IMM thread for applier functionality. + * + * @return NCSCC_RC_SUCCESS or NCSCC_RC_FAILURE + */ +uint32_t avnd_create_imm_thread() { + uint32_t rc = NCSCC_RC_SUCCESS; + pthread_t thread; + pthread_attr_t attr; + + TRACE_ENTER(); + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + if (pthread_create(&thread, &attr, AvndImm::imm_start, 0) != 0) { + LOG_ER("pthread_create FAILED: %s", strerror(errno)); + rc = NCSCC_RC_FAILURE; + } + + pthread_attr_destroy(&attr); + + TRACE_LEAVE(); + + return rc; +} + diff --git a/osaf/services/saf/amf/amfnd/include/Makefile.am b/osaf/services/saf/amf/amfnd/include/Makefile.am --- a/osaf/services/saf/amf/amfnd/include/Makefile.am +++ b/osaf/services/saf/amf/amfnd/include/Makefile.am @@ -29,6 +29,7 @@ noinst_HEADERS = \ avnd_evt.h \ avnd.h \ avnd_hc.h \ + avnd_imm.h \ avnd_mds.h \ avnd_mon.h \ avnd_pg.h \ diff --git a/osaf/services/saf/amf/amfnd/include/avnd.h b/osaf/services/saf/amf/amfnd/include/avnd.h --- a/osaf/services/saf/amf/amfnd/include/avnd.h +++ b/osaf/services/saf/amf/amfnd/include/avnd.h @@ -34,6 +34,7 @@ #define AVND_H #include <saImmOm.h> +#include <saImmOi.h> #include "amf.h" #include "ncs_main_papi.h" diff --git a/osaf/services/saf/amf/amfnd/include/avnd_evt.h b/osaf/services/saf/amf/amfnd/include/avnd_evt.h --- a/osaf/services/saf/amf/amfnd/include/avnd_evt.h +++ b/osaf/services/saf/amf/amfnd/include/avnd_evt.h @@ -110,6 +110,8 @@ typedef enum avnd_evt_type { AVND_EVT_PID_EXIT, AVND_EVT_TMR_QSCING_CMPL, + AVND_EVT_IMM, + AVND_EVT_MAX } AVND_EVT_TYPE; @@ -155,6 +157,11 @@ typedef struct avnd_pm_mon_evt { AVND_COMP_PM_REC *pm_rec; } AVND_PM_MON_EVT; +/* imm event definition */ +typedef struct avnd_imm_evt { + void *imm_evt; /* AvndImmEvt ptr */ +} AVND_IMM_EVT; + /* AVND top-level event structure */ typedef struct avnd_evt_tag { struct avnd_evt_tag *next; @@ -173,6 +180,7 @@ typedef struct avnd_evt_tag { AVND_CLC_EVT clc; AVND_COMP_FSM_EVT comp_fsm; AVND_PM_MON_EVT pm_evt; + AVND_IMM_EVT imm; } info; } AVND_EVT; diff --git a/osaf/services/saf/amf/amfnd/include/avnd_hc.h b/osaf/services/saf/amf/amfnd/include/avnd_hc.h --- a/osaf/services/saf/amf/amfnd/include/avnd_hc.h +++ b/osaf/services/saf/amf/amfnd/include/avnd_hc.h @@ -59,5 +59,6 @@ extern SaAisErrorT avnd_hc_config_get(st extern SaAisErrorT avnd_hctype_config_get(SaImmHandleT immOmHandle, const SaNameT *comptype_dn); extern AVND_HCTYPE *avnd_hctypedb_rec_get(const SaNameT *comp_type_dn, const SaAmfHealthcheckKeyT *key); extern uint32_t avnd_hc_oper_req(struct avnd_cb_tag *, AVSV_PARAM_INFO *param); +extern uint32_t avnd_hctype_oper_req(struct avnd_cb_tag *, AVSV_PARAM_INFO *param); #endif /* !AVND_HC_H */ diff --git a/osaf/services/saf/amf/amfnd/include/avnd_imm.h b/osaf/services/saf/amf/amfnd/include/avnd_imm.h new file mode 100644 --- /dev/null +++ b/osaf/services/saf/amf/amfnd/include/avnd_imm.h @@ -0,0 +1,148 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2014 The OpenSAF Foundation + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Author(s): Ericsson AB + * + */ + +/***************************************************************************** + DESCRIPTION: + + Classes used for implementing AMF node director as an IMM applier. + + ****************************************************************************** + */ + +#ifndef AVND_IMM_H +#define AVND_IMM_H + +#ifdef __cplusplus + +#include <vector> +#include <string> +#include "avnd.h" + +// +typedef enum { + AVND_SA_AMF_HEALTH_CHECK_TYPE = 0, + AVND_SA_AMF_CLASS_MAX +} AVND_AMF_CLASS_ID; + +//-------------------------------------------------------------------------- +// < \ingroup avndImm +// +// This class is used as a container for one IMM modify callback. +// > +//-------------------------------------------------------------------------- +class AvndImmEvt { +public: + // + explicit AvndImmEvt(const SaNameT& obj_name) : object_name_((const char*) obj_name.value, obj_name.length) {} + + // + ~AvndImmEvt(); + + // + std::string get_object_name() {return object_name_;} + + // + void set_mod_attr(const SaImmAttrModificationT_2& attr); + + // + typedef typename std::vector<SaImmAttrModificationT_2*>::const_iterator const_iterator; + const_iterator begin() const {return attr_.begin();} + const_iterator end() const {return attr_.end();} + +private: + // + AvndImmEvt(const AvndImmEvt&); + void operator=(const AvndImmEvt&); + + std::string object_name_; + + std::vector<SaImmAttrModificationT_2*> attr_; +}; + +//-------------------------------------------------------------------------- +// < \ingroup avndImm +// +// This class contains utility functions for IMM. +// > +//-------------------------------------------------------------------------- +class AvndImmUtil { +public: + // + static void deleteSaImmAttrValuesT(SaImmAttrValuesT_2& attr_value); + static void copySaImmAttrValuesT(SaImmAttrValuesT_2& to, const SaImmAttrValuesT_2& from); + static char *str_dup(const char *str); + static size_t value_size(SaImmValueTypeT attrValueType); + static AVSV_AMF_CLASS_ID object_name_to_class_type(const SaNameT* obj_name); + static void remove_attr(SaImmAttrModificationT_2* attr); +private: + AvndImmUtil(); + AvndImmUtil(const AvndImmUtil&); + void operator=(const AvndImmUtil&); +}; + +//-------------------------------------------------------------------------- +// < \ingroup avndImm +// +// This class contains IMM callback, init and set functions. +// > +//-------------------------------------------------------------------------- +class AvndImm { + public: + // + typedef uint32_t (*UpdateFn) (const std::string& dn, const SaImmAttrModificationT_2* attr); + + // + static void ccb_abort_cb(SaImmOiHandleT immoi_handle, SaImmOiCcbIdT ccb_id); + static SaAisErrorT ccb_object_delete_cb(SaImmOiHandleT immoi_handle, SaImmOiCcbIdT ccb_id, const SaNameT *object_name); + static void ccb_apply_cb(SaImmOiHandleT immoi_handle, SaImmOiCcbIdT ccb_id); + static SaAisErrorT ccb_completed_cb(SaImmOiHandleT immoi_handle, SaImmOiCcbIdT ccb_id); + static SaAisErrorT ccb_object_create_cb(SaImmOiHandleT immoi_handle, SaImmOiCcbIdT ccb_id, const SaImmClassNameT class_name, + const SaNameT *parent_name, const SaImmAttrValuesT_2 **attr); + static SaAisErrorT ccb_object_modify_cb(SaImmOiHandleT immoi_handle, SaImmOiCcbIdT ccb_id, const SaNameT *object_name, const SaImmAttrModificationT_2 **attr_mods); + static void *imm_start(void *); + + // + static uint32_t not_yet_implemented(const std::string& object_name, const SaImmAttrModificationT_2* imm_attr); + static uint32_t update_health_check_type(const std::string& object_name, const SaImmAttrModificationT_2* imm_attr); + + // + static SaVersionT immVersion_; + static SaImmOiHandleT immOiHandle_; + static SaImmOiHandleT immOmHandle_; + static SaSelectionObjectT imm_sel_obj_; + static UpdateFn update_callback_[AVSV_SA_AMF_CLASS_MAX]; + static const char *avnd_class_names_[]; + private: + static SaAisErrorT imm_init(); + static void imm_main(); + static SaAisErrorT imm_applier_set(); + static const SaImmOiCallbacksT_2 avnd_callbacks_; + + // + AvndImm(); + AvndImm(const AvndImmUtil&); + void operator=(const AvndImm&); +}; + +// +extern uint32_t avnd_evt_imm_evh(AVND_CB *cb, AVND_EVT *evt); +extern uint32_t avnd_create_imm_thread(); + +#endif /* __cplusclpus */ + +#endif /* AVND_IMM_H */ + diff --git a/osaf/services/saf/amf/amfnd/main.cc b/osaf/services/saf/amf/amfnd/main.cc --- a/osaf/services/saf/amf/amfnd/main.cc +++ b/osaf/services/saf/amf/amfnd/main.cc @@ -31,6 +31,7 @@ #include "immutil.h" #include "logtrace.h" #include "nid_api.h" +#include "avnd_imm.h" #define FD_MBX 0 #define FD_TERM 1 @@ -117,7 +118,8 @@ extern const AVND_EVT_HDLR g_avnd_func_l avnd_evt_comp_pres_fsm_evh, /* AVND_EVT_COMP_PRES_FSM_EV */ avnd_evt_last_step_term_evh, /* AVND_EVT_LAST_STEP_TERM */ avnd_evt_pid_exit_evh, /* AVND_EVT_PID_EXIT */ - avnd_evt_tmr_qscing_cmpl_evh /* AVND_EVT_TMR_QSCING_CMPL */ + avnd_evt_tmr_qscing_cmpl_evh, /* AVND_EVT_TMR_QSCING_CMPL */ + avnd_evt_imm_evh /* AVND_EVT_IMML */ }; /* global task handle */ @@ -273,6 +275,12 @@ uint32_t avnd_create(void) rc = NCSCC_RC_FAILURE; goto done; } + + rc = avnd_create_imm_thread(); + if (NCSCC_RC_SUCCESS != rc) { + rc = NCSCC_RC_FAILURE; + goto done; + } done: TRACE_LEAVE(); ------------------------------------------------------------------------------ Time is money. Stop wasting it! Get your web API in 5 minutes. www.restlet.com/download http://p.sf.net/sfu/restlet _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel