This ticket adds support for container/contained in amfd.
---
src/amf/amfd/comp.cc | 65 ++++++++++++++++++--
src/amf/amfd/comp.h | 4 +-
src/amf/amfd/comptype.cc | 6 +-
src/amf/amfd/csi.cc | 6 ++
src/amf/amfd/csi.h | 3 +
src/amf/amfd/ndproc.cc | 14 +++++
src/amf/amfd/node.cc | 29 +++++++++
src/amf/amfd/node.h | 1 +
src/amf/amfd/sg.cc | 29 +++++++++
src/amf/amfd/sg.h | 4 ++
src/amf/amfd/sgproc.cc | 142 ++++++++++++++++++++++++++++++++++++++++++-
src/amf/amfd/si.cc | 17 ++++++
src/amf/amfd/si.h | 1 +
src/amf/amfd/su.cc | 155 ++++++++++++++++++++++++++++++++++++++++++++++-
src/amf/amfd/su.h | 15 ++++-
src/amf/amfd/util.cc | 39 ++++++++++++
src/amf/amfd/util.h | 2 +
17 files changed, 517 insertions(+), 15 deletions(-)
diff --git a/src/amf/amfd/comp.cc b/src/amf/amfd/comp.cc
index 482322d2e..571ac34fb 100644
--- a/src/amf/amfd/comp.cc
+++ b/src/amf/amfd/comp.cc
@@ -73,7 +73,7 @@ void AVD_COMP::initialize() {
curr_num_csi_actv = {};
curr_num_csi_stdby = {};
comp_proxy_csi = {};
- comp_container_csi = {};
+ saAmfCompContainerCsi = {};
saAmfCompRestartCount = {};
saAmfCompCurrProxyName = {};
saAmfCompCurrProxiedNames = {};
@@ -357,7 +357,10 @@ static int is_config_valid(const std::string &dn,
0, &aname);
osafassert(rc == SA_AIS_OK);
- if (comptype_db->find(Amf::to_string(&aname)) == nullptr) {
+ AVD_COMP_TYPE *comptype(comptype_db->find(Amf::to_string(&aname)));
+ CcbUtilOperationData_t *ccbCompTypeOpData(nullptr);
+
+ if (comptype == nullptr) {
/* Comp type does not exist in current model, check CCB */
if (opdata == nullptr) {
report_ccb_validation_error(opdata, "'%s' does not exist in model",
@@ -365,7 +368,8 @@ static int is_config_valid(const std::string &dn,
return 0;
}
- if (ccbutil_getCcbOpDataByDN(opdata->ccbId, &aname) == nullptr) {
+ ccbCompTypeOpData = ccbutil_getCcbOpDataByDN(opdata->ccbId, &aname);
+ if (ccbCompTypeOpData == nullptr) {
report_ccb_validation_error(
opdata, "'%s' does not exist in existing model or in CCB",
osaf_extended_name_borrow(&aname));
@@ -399,6 +403,24 @@ static int is_config_valid(const std::string &dn,
return 0;
}
+ if ((comptype && IS_COMP_CONTAINED(comptype->saAmfCtCompCategory)) ||
+ (ccbCompTypeOpData &&
+ ccbCompTypeOpData->operationType == CCBUTIL_CREATE &&
+ immutil_getAttr(const_cast<SaImmAttrNameT>("saAmfCtCompCategory"),
+ ccbCompTypeOpData->param.create.attrValues,
+ 0, &value) == SA_AIS_OK &&
+ value & SA_AMF_COMP_CONTAINED)) {
+ rc = immutil_getAttr(const_cast<SaImmAttrNameT>("saAmfCompContainerCsi"),
+ attributes, 0, &value);
+ if (rc != SA_AIS_OK) {
+ report_ccb_validation_error(
+ opdata, "Contained component '%s' must have saAmfCompContainerCsi "
+ "attribute set", dn.c_str());
+ return 0;
+ }
+ }
+
+
#if 0
if ((comp->comp_info.category == AVSV_COMP_TYPE_SA_AWARE) &&
(comp->comp_info.init_len == 0)) {
LOG_ER("Sa Aware Component: instantiation command not
configured");
@@ -716,6 +738,20 @@ static AVD_COMP *comp_create(const std::string &dn,
&comp->comp_info.comp_restart) != SA_AIS_OK)
comp->comp_info.comp_restart = comptype->saAmfCtDefDisableRestart;
+ if (comp->contained()) {
+ SaNameT container_csi;
+
+ if (immutil_getAttr(const_cast<SaImmAttrNameT>("saAmfCompContainerCsi"),
+ attributes, 0, &container_csi) != SA_AIS_OK) {
+ LOG_ER("unable to get container csi for %s", dn.c_str());
+ goto done;
+ }
+
+ comp->saAmfCompContainerCsi = Amf::to_string(&container_csi);
+ //XXX TODO_70: verify db if container csi. DO we requre this.
+ container_csis.insert(comp->saAmfCompContainerCsi);
+ }
+
comp->max_num_csi_actv = -1; // TODO
comp->max_num_csi_stdby = -1; // TODO
@@ -770,6 +806,7 @@ SaAisErrorT avd_comp_config_get(const std::string &su_name,
AVD_SU *su) {
const_cast<SaImmAttrNameT>("saAmfCompQuiescingCompleteTimeout"),
const_cast<SaImmAttrNameT>("saAmfCompRecoveryOnError"),
const_cast<SaImmAttrNameT>("saAmfCompDisableRestart"),
+ const_cast<SaImmAttrNameT>("saAmfCompContainerCsi"),
nullptr};
TRACE_ENTER();
@@ -1735,9 +1772,9 @@ static void comp_ccb_apply_modify_hdlr(struct
CcbUtilOperationData *opdata) {
comp->comp_proxy_csi = Amf::to_string((SaNameT *)value);
} else if (!strcmp(attribute->attrName, "saAmfCompContainerCsi")) {
if (value_is_deleted)
- comp->comp_proxy_csi = "";
+ comp->saAmfCompContainerCsi = "";
else
- comp->comp_container_csi = Amf::to_string((SaNameT *)value);
+ comp->saAmfCompContainerCsi = Amf::to_string((SaNameT *)value);
} else {
osafassert(0);
}
@@ -1842,6 +1879,8 @@ void avd_comp_constructor(void) {
bool AVD_COMP::is_preinstantiable() const {
AVSV_COMP_TYPE_VAL category = comp_info.category;
return ((category == AVSV_COMP_TYPE_SA_AWARE) ||
+ (category == AVSV_COMP_TYPE_CONTAINER) ||
+ (category == AVSV_COMP_TYPE_CONTAINED) ||
(category == AVSV_COMP_TYPE_PROXIED_LOCAL_PRE_INSTANTIABLE) ||
(category == AVSV_COMP_TYPE_EXTERNAL_PRE_INSTANTIABLE));
}
@@ -1904,3 +1943,19 @@ bool AVD_COMP::proxied_npi() const {
AVD_COMP_TYPE *comptype = comptype_db->find(saAmfCompType);
return (IS_COMP_PROXIED_NPI(comptype->saAmfCtCompCategory));
}
+/**
+ * @brief Checks if component is a container comp.
+ * @Return true/false.
+ */
+bool AVD_COMP::container(void) const {
+ AVD_COMP_TYPE *comptype(comptype_db->find(saAmfCompType));
+ return (IS_COMP_CONTAINER(comptype->saAmfCtCompCategory));
+}
+/**
+ * @brief Checks if component is contained comp.
+ * @Return true/false.
+ */
+bool AVD_COMP::contained(void) const {
+ AVD_COMP_TYPE *comptype(comptype_db->find(saAmfCompType));
+ return (IS_COMP_CONTAINED(comptype->saAmfCtCompCategory));
+}
diff --git a/src/amf/amfd/comp.h b/src/amf/amfd/comp.h
index 1493d717c..4265f16d6 100644
--- a/src/amf/amfd/comp.h
+++ b/src/amf/amfd/comp.h
@@ -141,7 +141,7 @@ class AVD_COMP {
* Checkpointing - Sent update independently.
*/
std::string comp_proxy_csi;
- std::string comp_container_csi;
+ std::string saAmfCompContainerCsi;
/* runtime attributes */
SaAmfOperationalStateT saAmfCompOperState;
@@ -166,6 +166,8 @@ class AVD_COMP {
bool saaware() const;
bool proxied_pi() const;
bool proxied_npi() const;
+ bool container(void) const;
+ bool contained(void) const;
private:
void initialize();
diff --git a/src/amf/amfd/comptype.cc b/src/amf/amfd/comptype.cc
index 787c0bcb6..843a406aa 100644
--- a/src/amf/amfd/comptype.cc
+++ b/src/amf/amfd/comptype.cc
@@ -223,9 +223,8 @@ static bool config_is_valid(const std::string &dn,
attributes, 0, &category);
osafassert(rc == SA_AIS_OK);
- /* We do not support Proxy, Container and Contained as of now. */
- if (IS_COMP_PROXY(category) || IS_COMP_CONTAINER(category) ||
- IS_COMP_CONTAINED(category)) {
+ /* We do not support Proxy as of now. */
+ if (IS_COMP_PROXY(category)) {
report_ccb_validation_error(
opdata, "Unsupported saAmfCtCompCategory value '%u' for '%s'",
category,
dn.c_str());
@@ -312,6 +311,7 @@ static bool config_is_valid(const std::string &dn,
*/
if (IS_COMP_LOCAL(category) &&
!(IS_COMP_PROXIED(category) || IS_COMP_PROXIED_NPI(category)) &&
+ !IS_COMP_CONTAINER(category) && !IS_COMP_CONTAINED(category) &&
!IS_COMP_SAAWARE(category)) {
attr_name = "saAmfCtRelPathTerminateCmd";
diff --git a/src/amf/amfd/csi.cc b/src/amf/amfd/csi.cc
index 82829566c..f7e3730dd 100644
--- a/src/amf/amfd/csi.cc
+++ b/src/amf/amfd/csi.cc
@@ -26,6 +26,7 @@
#include "amf/amfd/proc.h"
AmfDb<std::string, AVD_CSI> *csi_db = nullptr;
+std::set<std::string> container_csis;
//
AVD_COMP *AVD_CSI::find_assigned_comp(
@@ -1670,3 +1671,8 @@ void avd_compcsi_cleanup_imm_object(AVD_CL_CB *cb) {
done:
TRACE_LEAVE();
}
+
+bool AVD_CSI::is_container_csi(void) const {
+ auto iter(container_csis.find(name));
+ return (iter != container_csis.end()) ? true : false;
+}
diff --git a/src/amf/amfd/csi.h b/src/amf/amfd/csi.h
index 837fbc67d..166d9dec4 100644
--- a/src/amf/amfd/csi.h
+++ b/src/amf/amfd/csi.h
@@ -98,6 +98,8 @@ class AVD_CSI {
const std::string &cstype, const AVD_SU_SI_REL *sisu,
const std::vector<AVD_COMP *> &list_of_comp);
+ bool is_container_csi(void) const;
+
private:
AVD_CSI();
// disallow copy and assign
@@ -106,6 +108,7 @@ class AVD_CSI {
};
extern AmfDb<std::string, AVD_CSI> *csi_db;
+extern std::set<std::string> container_csis;
class AVD_CS_TYPE {
public:
diff --git a/src/amf/amfd/ndproc.cc b/src/amf/amfd/ndproc.cc
index 31d2263d2..eb5d2b3d8 100644
--- a/src/amf/amfd/ndproc.cc
+++ b/src/amf/amfd/ndproc.cc
@@ -1113,6 +1113,20 @@ void avd_data_update_req_evh(AVD_CL_CB *cb, AVD_EVT
*evt) {
/* send response to pending clm callback */
if (su->su_on_node->clm_pend_inv != 0)
clm_pend_response(su, static_cast<SaAmfPresenceStateT>(l_val));
+
+ /*
+ * If the contained su has finished terminating we can now finish
+ * with the container su.
+ */
+ if (su->contained() && l_val == SA_AMF_PRESENCE_UNINSTANTIATED) {
+ AVD_SU *container_su(su->get_container_su_on_same_node());
+
+ if (container_su->wait_for_contained_to_quiesce) {
+ // XXX fix me, could be quiescing
+ avd_sg_su_si_mod_snd(cb, container_su, SA_AMF_HA_QUIESCED);
+ container_su->wait_for_contained_to_quiesce = false;
+ }
+ }
} else {
/* log error that a the value len is invalid */
LOG_ER("%s:%u: %u", __FILE__, __LINE__,
diff --git a/src/amf/amfd/node.cc b/src/amf/amfd/node.cc
index 0ffcfb782..b5ff0eab3 100644
--- a/src/amf/amfd/node.cc
+++ b/src/amf/amfd/node.cc
@@ -1676,3 +1676,32 @@ bool AVD_AVND::is_campaign_set_for_all_sus() const {
return false;
}
}
+
+void AVD_AVND::instantiate_contained_sus(AVD_SU *container_su,
+ const AVD_CSI *container_csi) {
+ TRACE_ENTER();
+ for (auto &su : list_of_su) {
+ if (su == container_su)
+ continue;
+ if ((su->contained() == false) ||
+ (su->list_of_comp.empty() == true) ||
+ (su->saAmfSUPresenceState == SA_AMF_PRESENCE_INSTANTIATED))
+ continue;
+ if (su->list_of_comp.front()->saAmfCompContainerCsi ==
container_csi->name) {
+ if (((su->su_on_node->node_state == AVD_AVND_STATE_PRESENT) ||
+ (su->su_on_node->node_state == AVD_AVND_STATE_NO_CONFIG) ||
+ (su->su_on_node->node_state == AVD_AVND_STATE_NCS_INIT)) &&
+ ((su->su_on_node->saAmfNodeAdminState !=
SA_AMF_ADMIN_LOCKED_INSTANTIATION) &&
+ (su->sg_of_su->saAmfSGAdminState !=
SA_AMF_ADMIN_LOCKED_INSTANTIATION)) &&
+ ((su->saAmfSUOperState == SA_AMF_OPERATIONAL_ENABLED) ||
+ (su->sg_of_su->sg_ncs_spec == true)) &&
+ (su->sg_of_su->saAmfSGNumPrefInserviceSUs >
+ sg_instantiated_su_count(su->sg_of_su))) {
+ if (avd_instantiate_contained_su(avd_cb, container_su, su, false) ==
NCSCC_RC_SUCCESS) {
+ su->set_term_state(false);
+ }
+ }
+ }
+ }
+ TRACE_LEAVE();
+}
diff --git a/src/amf/amfd/node.h b/src/amf/amfd/node.h
index e64bf8c93..55e50504a 100644
--- a/src/amf/amfd/node.h
+++ b/src/amf/amfd/node.h
@@ -148,6 +148,7 @@ class AVD_AVND {
bool is_campaign_set_for_all_sus() const;
// Member functions.
void node_sus_termstate_set(bool term_state) const;
+ void instantiate_contained_sus(AVD_SU* su, const AVD_CSI *container_csi);
private:
void initialize();
diff --git a/src/amf/amfd/sg.cc b/src/amf/amfd/sg.cc
index f973e3a97..83af5292b 100644
--- a/src/amf/amfd/sg.cc
+++ b/src/amf/amfd/sg.cc
@@ -497,6 +497,14 @@ SaAisErrorT avd_sg_config_get(const std::string &app_dn,
AVD_APP *app) {
error = SA_AIS_ERR_FAILED_OPERATION;
goto done2;
}
+
+ if ((sg->any_container_su() == true) &&
+ (sg->sg_redundancy_model != SA_AMF_N_WAY_ACTIVE_REDUNDANCY_MODEL)) {
+ LOG_ER("%s: red model for container sg must be N-Way Active: %u",
+ sg->name.c_str(),sg->sg_redundancy_model);
+ error = SA_AIS_ERR_FAILED_OPERATION;
+ goto done2;
+ }
}
if (rc == SA_AIS_ERR_NOT_EXIST) {
@@ -2400,3 +2408,24 @@ bool AVD_SG::find_instantiable_same_rank_su(AVD_SU *su) {
}
return false;
}
+
+/**
+ * @brief Checks if any su of Sg is a container su.
+ * @return true/false
+ */
+bool AVD_SG::any_container_su(void) const {
+ return (std::any_of(list_of_su.begin(), list_of_su.end(),
+ [&](AVD_SU *su) -> bool {
+ return su->container();
+ }));
+}
+/**
+ * @brief Checks if any su of Sg is a contained su.
+ * @return true/false
+ */
+bool AVD_SG::any_contained_su(void) const {
+ return (std::any_of(list_of_su.begin(), list_of_su.end(),
+ [&](AVD_SU *su) -> bool {
+ return su->contained();
+ }));
+}
diff --git a/src/amf/amfd/sg.h b/src/amf/amfd/sg.h
index 81595a2b1..426f1ba4d 100644
--- a/src/amf/amfd/sg.h
+++ b/src/amf/amfd/sg.h
@@ -451,6 +451,10 @@ class AVD_SG {
// Checks if si_equal_distribution is configured for the SG.
bool is_equal() const;
bool find_instantiable_same_rank_su(AVD_SU *su);
+ //Checks if any SU of sg is a container su.
+ bool any_container_su(void) const;
+ //Checks if any SU of sg is a contained su.
+ bool any_contained_su(void) const;
private:
// disallow copy and assign, TODO(hafe) add common macro for this
diff --git a/src/amf/amfd/sgproc.cc b/src/amf/amfd/sgproc.cc
index 2bee8754d..7fba62ba7 100644
--- a/src/amf/amfd/sgproc.cc
+++ b/src/amf/amfd/sgproc.cc
@@ -41,6 +41,8 @@
#include "amf/amfd/si_dep.h"
#include "amf/amfd/cluster.h"
+extern bool all_assignments_done(const AVD_SU *);
+
/**
* @brief While creating compcsi relationship in SUSI, AMF may assign
* a dependent csi to a component in the SU when its one or more
@@ -1134,6 +1136,54 @@ void
process_su_si_response_for_surestart_admin_op(AVD_SU *su) {
}
TRACE_LEAVE();
}
+
+static void process_su_si_response_for_container_contained(
+ AVD_CL_CB *cb, AVD_SU *su, SaAmfHAStateT state, AVSV_SUSI_ACT msg_act) {
+ TRACE_ENTER();
+
+ if (su->container() || su->contained()) {
+ TRACE("su: %s state: %i msg_act: %i", su->name.c_str(), state, msg_act);
+
+ if (su->contained() &&
+ ((state == SA_AMF_HA_QUIESCED && msg_act == AVSV_SUSI_ACT_DEL) ||
+ (state == SA_AMF_HA_STANDBY && msg_act == AVSV_SUSI_ACT_DEL))) {
+ // notify container su that contained has quiesced and removed
+ AVD_SU *container_su(su->get_container_su_on_same_node());
+
+ TRACE("container: %s wait: %i",
+ container_su->name.c_str(),
+ container_su->wait_for_contained_to_quiesce);
+
+ if (container_su->wait_for_contained_to_quiesce) {
+ // contained SU has been removed, now terminate it
+ if (avd_snd_presence_msg(avd_cb, su, true) == NCSCC_RC_SUCCESS)
+ su->set_term_state(true);
+
+ /*
+ * If all the contained SUs are done change the admin state of the
+ * contained SG back to unlocked.
+ */
+ bool all_unassigned(true);
+ for (const auto &iter : su->sg_of_su->list_of_su) {
+ if (iter->list_of_susi != AVD_SU_SI_REL_NULL) {
+ all_unassigned = false;
+ break;
+ }
+ }
+
+ if (container_su->sg_of_su->saAmfSGAdminState == SA_AMF_ADMIN_LOCKED &&
+ all_unassigned) {
+ su->sg_of_su->saAmfSGAdminState = SA_AMF_ADMIN_UNLOCKED;
+ }
+ }
+ } else if (su->container() && state == SA_AMF_HA_ACTIVE)
+ su->instantiate_associated_contained_sus();
+ }
+
+ TRACE_LEAVE();
+ return;
+}
+
/*****************************************************************************
* Function: avd_su_si_assign_func
*
@@ -1247,6 +1297,14 @@ void avd_su_si_assign_evh(AVD_CL_CB *cb, AVD_EVT *evt) {
TRACE("%u", n2d_msg->msg_info.n2d_su_si_assign.msg_act);
switch (n2d_msg->msg_info.n2d_su_si_assign.msg_act) {
case AVSV_SUSI_ACT_DEL:
+ if (su->contained()) {
+ AVD_SU *container_su(su->get_container_su_on_same_node());
+ if (container_su->wait_for_contained_to_quiesce &&
+ container_su->sg_of_su->saAmfSGAdminState ==
+ SA_AMF_ADMIN_LOCKED) {
+ avd_sg_su_oper_list_del(cb, su, false);
+ }
+ }
break;
case AVSV_SUSI_ACT_MOD:
@@ -1724,6 +1782,12 @@ void avd_su_si_assign_evh(AVD_CL_CB *cb, AVD_EVT *evt) {
su->su_on_node->clm_pend_inv = 0;
} /* else wait for some more time */
}
+
+ process_su_si_response_for_container_contained(
+ cb,
+ su,
+ n2d_msg->msg_info.n2d_su_si_assign.ha_state,
+ n2d_msg->msg_info.n2d_su_si_assign.msg_act);
}
/* Check whether the node belonging to this su is disable and susi of all su
@@ -1813,7 +1877,8 @@ void avd_sg_app_node_su_inst_func(AVD_CL_CB *cb, AVD_AVND
*avnd) {
if (cb->init_state == AVD_INIT_DONE) {
for (const auto &i_su : avnd->list_of_su) {
- if ((i_su->term_state == false) &&
+ if (!i_su->contained() && // contained sus are instantiated by container
+ (i_su->term_state == false) &&
(i_su->saAmfSUPresenceState == SA_AMF_PRESENCE_UNINSTANTIATED) &&
(i_su->saAmfSUAdminState != SA_AMF_ADMIN_LOCKED_INSTANTIATION) &&
(i_su->sg_of_su->saAmfSGAdminState !=
@@ -1994,7 +2059,8 @@ uint32_t avd_sg_app_su_inst_func(AVD_CL_CB *cb, AVD_SG
*sg) {
num_insvc_su++;
}
- } else if ((i_su->saAmfSUPreInstantiable == true) &&
+ } else if (!i_su->contained() && // contained su instantiated by
container
+ (i_su->saAmfSUPreInstantiable == true) &&
(i_su->saAmfSUPresenceState ==
SA_AMF_PRESENCE_UNINSTANTIATED) &&
((i_su->saAmfSUAdminState == SA_AMF_ADMIN_UNLOCKED) ||
@@ -2423,6 +2489,71 @@ done:
return rc;
}
+static uint32_t shutdown_contained_sus(AVD_CL_CB *cb, AVD_SU *container_su,
+ SaAmfHAStateT state) {
+ TRACE_ENTER();
+
+ uint32_t rc(NCSCC_RC_FAILURE);
+
+ // get the container csi
+ AVD_COMP_CSI_REL *container_csi_rel(nullptr);
+
+ for (const auto &comp : container_su->list_of_comp) {
+ if (comp->container()) {
+ for (const auto &si : container_su->sg_of_su->list_of_si) {
+ for (AVD_CSI *csi = si->list_of_csi; csi; csi =
csi->si_list_of_csi_next) {
+ for (AVD_COMP_CSI_REL *compcsi = csi->list_compcsi; compcsi;
+ compcsi = compcsi->csi_csicomp_next) {
+ if (compcsi->comp == comp) {
+ TRACE("found container csi: %s", compcsi->csi->name.c_str());
+ container_csi_rel = compcsi;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ const std::string& container_csi(container_csi_rel->csi->name);
+
+ for (auto &su : container_su->su_on_node->list_of_su) {
+ if (su == container_su)
+ continue;
+ if ((su->contained() == false) ||
+ (su->list_of_comp.empty() == true))
+ continue;
+ if (su->list_of_comp.front()->saAmfCompContainerCsi == container_csi) {
+ su->set_readiness_state(SA_AMF_READINESS_OUT_OF_SERVICE);
+
+ if (su->list_of_susi->state == SA_AMF_HA_ACTIVE)
+ rc = avd_sg_su_si_mod_snd(cb, su, SA_AMF_HA_QUIESCED);
+ else
+ rc = avd_sg_su_si_del_snd(cb, su);
+
+ if (rc != NCSCC_RC_SUCCESS)
+ goto done;
+
+ if (container_su->sg_of_su->saAmfSGAdminState == SA_AMF_ADMIN_LOCKED) {
+ // this is dangerous...
+ // XXX use ng_using_saAmfSGAdminState
+ su->sg_of_su->saAmfSGAdminState = SA_AMF_ADMIN_LOCKED;
+
+ su->sg_of_su->set_fsm_state(AVD_SG_FSM_SG_ADMIN);
+ } else {
+ su->sg_of_su->set_fsm_state(AVD_SG_FSM_SU_OPER);
+ }
+
+ avd_sg_su_oper_list_add(cb, su, false);
+ }
+ }
+
+done:
+ return rc;
+
+ TRACE_LEAVE();
+}
+
/*****************************************************************************
* Function: avd_sg_su_si_mod_snd
*
@@ -2456,6 +2587,13 @@ uint32_t avd_sg_su_si_mod_snd(AVD_CL_CB *cb, AVD_SU *su,
SaAmfHAStateT state) {
goto done;
}
+ if (su->container() && !su->wait_for_contained_to_quiesce) {
+ TRACE("this is a container su; need to shut down contained sus");
+ rc = shutdown_contained_sus(cb, su, state);
+ su->wait_for_contained_to_quiesce = true;
+ goto done;
+ }
+
/* change the state for all assignments to the specified state. */
i_susi = su->list_of_susi;
while (i_susi != AVD_SU_SI_REL_NULL) {
diff --git a/src/amf/amfd/si.cc b/src/amf/amfd/si.cc
index cf026d7b8..5308a7ac8 100644
--- a/src/amf/amfd/si.cc
+++ b/src/amf/amfd/si.cc
@@ -703,6 +703,13 @@ SaAisErrorT avd_si_config_get(AVD_APP *app) {
if (avd_sirankedsu_config_get(si_str, si) != SA_AIS_OK) goto done2;
if (avd_csi_config_get(si_str, si) != SA_AIS_OK) goto done2;
+
+ if ((si->sg_of_si != nullptr) && (si->sg_of_si->any_container_su() == true)
+ && (si->csi_count() > 1)) {
+ LOG_ER("More than one CSIs configured in a container si:'%s'",
+ si->name.c_str());
+ goto done2;
+ }
}
if (rc == SA_AIS_ERR_NOT_EXIST) {
@@ -1917,3 +1924,13 @@ SaAisErrorT AVD_SI::si_swap_validate() {
done:
return rc;
}
+
+uint32_t AVD_SI::csi_count(void) const {
+ uint32_t count(0);
+ for (const AVD_CSI *csi(list_of_csi);
+ csi;
+ csi = csi->si_list_of_csi_next) {
+ count++;
+ }
+ return count;
+}
diff --git a/src/amf/amfd/si.h b/src/amf/amfd/si.h
index 45b37cc33..cca42a400 100644
--- a/src/amf/amfd/si.h
+++ b/src/amf/amfd/si.h
@@ -155,6 +155,7 @@ class AVD_SI {
uint32_t count_sisu_with(SaAmfHAStateT ha);
bool is_all_sponsor_si_unassigned() const;
bool is_all_dependent_si_unassigned() const;
+ uint32_t csi_count(void) const;
private:
bool is_assigned() const { return list_of_sisu ? true : false; }
diff --git a/src/amf/amfd/su.cc b/src/amf/amfd/su.cc
index c3609d8aa..2c8256a37 100644
--- a/src/amf/amfd/su.cc
+++ b/src/amf/amfd/su.cc
@@ -64,6 +64,7 @@ void AVD_SU::initialize() {
pend_cbk.invocation = 0;
pend_cbk.admin_oper = (SaAmfAdminOperationIdT)0;
surestart = false;
+ wait_for_contained_to_quiesce = false;
}
AVD_SU::AVD_SU() { initialize(); }
@@ -748,6 +749,23 @@ SaAisErrorT avd_su_config_get(const std::string &sg_name,
AVD_SG *sg) {
error = SA_AIS_ERR_FAILED_OPERATION;
goto done2;
}
+
+ if (su->any_container_comp() == true) {
+ if (su->container() == false) {
+ LOG_ER("%s: comps of other category mixed with container comp: %u",
+ su->name.c_str(), error);
+ error = SA_AIS_ERR_FAILED_OPERATION;
+ goto done2;
+ }
+ }
+ if (su->any_contained_comp() == true) {
+ if (su->contained() == false) {
+ LOG_ER("%s: comps of other category mixed with contained comp: %u",
+ su->name.c_str(), error);
+ error = SA_AIS_ERR_FAILED_OPERATION;
+ goto done2;
+ }
+ }
}
if (rc == SA_AIS_ERR_NOT_EXIST) {
@@ -1120,6 +1138,9 @@ done:
void AVD_SU::unlock_instantiation(SaImmOiHandleT immoi_handle,
SaInvocationT invocation) {
AVD_AVND *node = get_node_ptr();
+ bool is_container_ready = true;
+ AVD_SU *container_ptr = nullptr;
+ uint32_t rc;
TRACE_ENTER2("'%s'", name.c_str());
@@ -1149,6 +1170,15 @@ void AVD_SU::unlock_instantiation(SaImmOiHandleT
immoi_handle,
goto done;
}
+ if (contained() == true) {
+ container_ptr = get_container_su_on_same_node();
+ if ((container_ptr == nullptr) ||
+ (container_ptr->is_ready_for_contained() == false)) {
+ is_container_ready = false;
+ TRACE("Container su not available or ready.");
+ }
+ }
+
/* Middleware sus are not enabled until node joins. During
starting of opensaf, if mw su is locked-in and unlock-in
command is issued, su should get instantiated. */
@@ -1160,10 +1190,16 @@ void AVD_SU::unlock_instantiation(SaImmOiHandleT
immoi_handle,
((saAmfSUOperState == SA_AMF_OPERATIONAL_ENABLED) ||
(sg_of_su->sg_ncs_spec == true)) &&
(sg_of_su->pref_inservice_sus() >
- sg_instantiated_su_count(sg_of_su))) {
+ sg_instantiated_su_count(sg_of_su)) &&
+ (is_container_ready == true)) {
/* When the SU will instantiate then prescence state change message will
come and so store the callback parameters to send response later on. */
- if (avd_snd_presence_msg(avd_cb, this, false) == NCSCC_RC_SUCCESS) {
+ if (contained() == true)
+ rc = avd_instantiate_contained_su(avd_cb, container_ptr, this, false);
+ else
+ rc = avd_snd_presence_msg(avd_cb, this, false);
+
+ if (rc == NCSCC_RC_SUCCESS) {
set_term_state(false);
set_admin_state(SA_AMF_ADMIN_LOCKED);
pend_cbk.admin_oper = SA_AMF_ADMIN_UNLOCK_INSTANTIATION;
@@ -2359,7 +2395,7 @@ AVD_AVND *AVD_SU::get_node_ptr(void) const {
* @param su
* @return true if SU can be made in-service
*/
-bool AVD_SU::is_in_service(void) {
+bool AVD_SU::is_in_service(void) const {
AVD_AVND *node = get_node_ptr();
const AVD_SG *sg = sg_of_su;
const AVD_APP *app = sg->app;
@@ -2803,3 +2839,116 @@ uint32_t AVD_SU::count_susi_without_fsm(uint32_t fsm) {
}
return count;
}
+
+/**
+ * @brief Checks if all comps of SU are container comps.
+ * @return true/false
+ */
+bool AVD_SU::container(void) const {
+ if (std::all_of(list_of_comp.begin(), list_of_comp.end(),
+ [&](AVD_COMP *comp) -> bool {
+ return comp->container();
+ })) {
+ return true;
+ } else {
+ return false;
+ }
+}
+/**
+ * @brief Checks if all comps of SU are contained comps.
+ * @return true/false
+ */
+bool AVD_SU::contained(void) const {
+ if (std::all_of(list_of_comp.begin(), list_of_comp.end(),
+ [&](AVD_COMP *comp) -> bool {
+ return comp->contained();
+ })) {
+ return true;
+ } else {
+ return false;
+ }
+}
+/**
+ * @brief Checks if any comp of SU is a container comp.
+ * @return true/false
+ */
+bool AVD_SU::any_container_comp(void) const {
+ return (std::any_of(list_of_comp.begin(), list_of_comp.end(),
+ [&](AVD_COMP *comp) -> bool {
+ return comp->container();
+ }));
+
+}
+
+/**
+ * @brief Checks if any comp of SU is a contained comp.
+ * @return true/false
+ */
+bool AVD_SU::any_contained_comp(void) const {
+ return (std::any_of(list_of_comp.begin(), list_of_comp.end(),
+ [&](AVD_COMP *comp) -> bool {
+ return comp->contained();
+ }));
+}
+
+bool AVD_SU::is_ready_for_contained(void) const {
+ if ((container() == true) && (list_of_susi != nullptr) &&
+ (is_in_service() == true) && (any_container_csi_assigned() == true))
+ return true;
+ return false;
+}
+
+void AVD_SU::instantiate_associated_contained_sus(void) {
+ TRACE_ENTER();
+ if (is_ready_for_contained() == false) {
+ TRACE_LEAVE();
+ return;
+ }
+ for (AVD_SU_SI_REL *susi = list_of_susi; susi != nullptr;
+ susi = susi->su_next) {
+ if (susi->fsm != AVD_SU_SI_STATE_ASGND)
+ continue;
+ for (AVD_COMP_CSI_REL *compcsi = susi->list_of_csicomp; compcsi;
+ compcsi = compcsi->susi_csicomp_next) {
+ if (compcsi->csi->is_container_csi() == true) {
+ su_on_node->instantiate_contained_sus(this, compcsi->csi);
+ }
+ }
+ }
+ TRACE_LEAVE();
+}
+
+bool AVD_SU::any_container_csi_assigned(void) const {
+ for (AVD_SU_SI_REL *susi = list_of_susi; susi != nullptr;
+ susi = susi->su_next) {
+ if (susi->fsm != AVD_SU_SI_STATE_ASGND)
+ continue;
+ for (AVD_COMP_CSI_REL *compcsi = susi->list_of_csicomp; compcsi;
+ compcsi = compcsi->susi_csicomp_next) {
+ if (compcsi->csi->is_container_csi() == true)
+ return true;
+ }
+ }
+ return false;
+}
+
+AVD_CSI *AVD_SU::get_container_csi(void) {
+ if (list_of_comp.empty())
+ return nullptr;
+ auto comp = list_of_comp.front();
+ return csi_db->find(comp->saAmfCompContainerCsi);
+}
+
+AVD_SU *AVD_SU::get_container_su_on_same_node(void) {
+ AVD_CSI *container_csi = get_container_csi();
+ if (container_csi != nullptr) {
+ for (AVD_COMP_CSI_REL *compcsi = container_csi->list_compcsi;
+ compcsi;
+ compcsi = compcsi->csi_csicomp_next) {
+ if (compcsi->comp->su->su_on_node == su_on_node)
+ return compcsi->comp->su;
+ }
+ }
+ //TODO:70: return a higher rank su always. It should match other function.
+ return nullptr;
+}
diff --git a/src/amf/amfd/su.h b/src/amf/amfd/su.h
index cf29f25de..7afc5abee 100644
--- a/src/amf/amfd/su.h
+++ b/src/amf/amfd/su.h
@@ -37,6 +37,7 @@
#include "amf/common/amf_db_template.h"
class AVD_SG;
+class AVD_CSI;
class AVD_SUTYPE;
/**
@@ -88,6 +89,8 @@ class AVD_SU {
int su_act_state; // not used, kept for EDU, remove later
+ bool wait_for_contained_to_quiesce;
+
AVD_SG *sg_of_su; /* the service group of this SU */
AVD_AVND *su_on_node; /* the node on which this SU resides */
struct avd_su_si_rel_tag
@@ -122,7 +125,7 @@ class AVD_SU {
void remove_from_model();
void set_su_switch(SaToggleState state, bool wrt_to_imm = true);
AVD_AVND *get_node_ptr(void) const;
- bool is_in_service(void);
+ bool is_in_service(void) const;
bool is_instantiable(void);
void reset_all_comps_assign_flag();
AVD_COMP *find_unassigned_comp_that_provides_cstype(
@@ -156,6 +159,16 @@ class AVD_SU {
void set_surestart(bool state);
bool get_surestart() const;
void update_susis_in_imm_and_ntf(SaAmfHAStateT ha_state) const;
+ bool any_container_comp(void) const;
+ bool any_contained_comp(void) const;
+ bool container(void) const;
+ bool contained(void) const;
+ void instantiate_associated_contained_sus(void);
+ bool is_ready_for_contained(void) const;
+ bool any_container_csi_assigned(void) const;
+ AVD_CSI *get_container_csi(void);
+ AVD_SU *get_container_su_on_same_node(void);
+
private:
void initialize();
diff --git a/src/amf/amfd/util.cc b/src/amf/amfd/util.cc
index 288d77483..14a4e0485 100644
--- a/src/amf/amfd/util.cc
+++ b/src/amf/amfd/util.cc
@@ -2123,3 +2123,42 @@ done:
delete d2n_msg;
return rc;
}
+
+uint32_t avd_instantiate_contained_su(AVD_CL_CB *cb, AVD_SU *container_su,
+ AVD_SU *contained_su, bool term_state) {
+ uint32_t rc = NCSCC_RC_FAILURE;
+ AVD_DND_MSG *d2n_msg;
+ AVD_AVND *node = container_su->get_node_ptr();
+
+ TRACE_ENTER2("%s '%s'", (term_state == true) ? "Terminate" : "Instantiate",
+ contained_su->name.c_str());
+
+ /* prepare the node update message. */
+ d2n_msg = new AVSV_DND_MSG();
+ SaNameT container_su_name, contained_su_name;
+ osaf_extended_name_alloc(container_su->name.c_str(), &container_su_name);
+ osaf_extended_name_alloc(contained_su->name.c_str(), &contained_su_name);
+
+ /* prepare the SU presence state change notification message */
+ d2n_msg->msg_type = AVSV_D2N_CONTAINED_SU_MSG;
+ d2n_msg->msg_info.d2n_contained_su_msg_info.msg_id = ++(node->snd_msg_id);
+ d2n_msg->msg_info.d2n_contained_su_msg_info.node_id = node->node_info.nodeId;
+ d2n_msg->msg_info.d2n_contained_su_msg_info.container_su_name =
container_su_name;
+ d2n_msg->msg_info.d2n_contained_su_msg_info.contained_su_name =
contained_su_name;
+ d2n_msg->msg_info.d2n_contained_su_msg_info.term_state = term_state;
+
+ TRACE("Sending %u to %x", AVSV_D2N_CONTAINED_SU_MSG, node->node_info.nodeId);
+
+ if (avd_d2n_msg_snd(cb, node, d2n_msg) != NCSCC_RC_SUCCESS) {
+ LOG_ER("%s: snd to %x failed", __FUNCTION__, node->node_info.nodeId);
+ d2n_msg_free(d2n_msg);
+ --(node->snd_msg_id);
+ goto done;
+ }
+
+ m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, (node), AVSV_CKPT_AVND_SND_MSG_ID);
+ rc = NCSCC_RC_SUCCESS;
+done:
+ TRACE_LEAVE2("%u", rc);
+ return rc;
+}
diff --git a/src/amf/amfd/util.h b/src/amf/amfd/util.h
index 28709493b..39ca5a344 100644
--- a/src/amf/amfd/util.h
+++ b/src/amf/amfd/util.h
@@ -122,5 +122,7 @@ uint32_t avd_snd_compcsi_msg(AVD_COMP *comp, AVD_CSI *csi,
avd_comp_csi_rel_tag *compcsi,
AVSV_COMPCSI_ACT act);
uint32_t avd_send_reboot_msg_directly(AVD_AVND *node);
+uint32_t avd_instantiate_contained_su(AVD_CL_CB *cb, AVD_SU *container_su,
+ AVD_SU *contained_su, bool term_state);
#endif // AMF_AMFD_UTIL_H_
--
2.14.4
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel