amfsg.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671
  1. /** @file amfsg.c
  2. *
  3. * Copyright (c) 2002-2006 MontaVista Software, Inc.
  4. * Author: Steven Dake (sdake@mvista.com)
  5. *
  6. * Copyright (c) 2006 Ericsson AB.
  7. * Author: Hans Feldt, Anders Eriksson, Lars Holm
  8. * - Introduced AMF B.02 information model
  9. * - Use DN in API and multicast messages
  10. * - (Re-)Introduction of event based multicast messages
  11. * - Refactoring of code into several AMF files
  12. * - Component/SU restart, SU failover
  13. * - Constructors/destructors
  14. * - Serializers/deserializers
  15. *
  16. * All rights reserved.
  17. *
  18. *
  19. * This software licensed under BSD license, the text of which follows:
  20. *
  21. * Redistribution and use in source and binary forms, with or without
  22. * modification, are permitted provided that the following conditions are met:
  23. *
  24. * - Redistributions of source code must retain the above copyright notice,
  25. * this list of conditions and the following disclaimer.
  26. * - Redistributions in binary form must reproduce the above copyright notice,
  27. * this list of conditions and the following disclaimer in the documentation
  28. * and/or other materials provided with the distribution.
  29. * - Neither the name of the MontaVista Software, Inc. nor the names of its
  30. * contributors may be used to endorse or promote products derived from this
  31. * software without specific prior written permission.
  32. *
  33. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  34. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  35. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  36. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  37. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  38. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  39. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  40. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  41. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  42. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  43. * THE POSSIBILITY OF SUCH DAMAGE.
  44. *
  45. * AMF Service Group Class Implementation
  46. *
  47. * This file contains functions for handling AMF-service groups(SGs). It can be
  48. * viewed as the implementation of the AMF Service Group class (called SG)
  49. * as described in SAI-Overview-B.02.01. The SA Forum specification
  50. * SAI-AIS-AMF-B.02.01 has been used as specification of the behaviour
  51. * and is referred to as 'the spec' below.
  52. *
  53. * The functions in this file are responsible for:
  54. * -on request start the service group by instantiating the contained SUs
  55. * -on request assign the service instances it protects to the in-service
  56. * service units it contains respecting as many as possible of the configured
  57. * requirements for the group
  58. * -create and delete an SI-assignment object for each relation between
  59. * an SI and an SU
  60. * -order each contained SU to create and delete CSI-assignments
  61. * -request the Service Instance class (SI) to execute the transfer of the
  62. * HA-state set/remove requests to each component involved
  63. * -fully control the execution of component failover and SU failover
  64. * -on request control the execution of the initial steps of node switchover
  65. * and node failover
  66. * -fully handle the auto adjust procedure
  67. *
  68. * Currently only the 'n+m' redundancy model is implemented. It is the
  69. * ambition to identify n+m specific variables and functions and add the suffix
  70. * '_nplusm' to them so that they can be easily recognized.
  71. *
  72. * When SG is requested to assign workload to all SUs or all SUs hosted on
  73. * a specific node, a procedure containing several steps is executed:
  74. * <1> An algorithm is executed which assigns SIs to SUs respecting the rules
  75. * that has been configured for SG. The algorithm also has to consider
  76. * if assignments between som SIs and SUs already exist. The scope of this
  77. * algorithm is to create SI-assignments and set up requested HA-state for
  78. * each assignment but not to transfer those HA-states to the components.
  79. * <2> All SI-assignments with a requested HA state == ACTIVE are transferred
  80. * to the components concerned before any STANDBY assignments are
  81. * transferred. All components have to acknowledge the setting of the
  82. * ACTIVE HA state before the transfer of any STANDBY assignment is
  83. * initiated.
  84. * <3> All active assignments can not be transferred at the same time to the
  85. * different components because the rules for dependencies between SI and
  86. * SI application wide and CSI and CSI within one SI, has to be respected.
  87. *
  88. * SG is fully responsible for step <1> but not fully responsible for handling
  89. * step <2> and <3>. However, SG uses an attribute called 'dependency level'
  90. * when requsted to assign workload. This parameter refers to an integer that
  91. * has been calculated initially for each SI. The 'dependency level' indicates
  92. * to which extent an SI depends on other SIs such that an SI that depends on
  93. * no other SI is on dependecy_level == 1, an SI that depends only on an SI on
  94. * dependency_level == 1 is on dependency-level == 2.
  95. * An SI that depends on several SIs gets a
  96. * dependency_level that is one unit higher than the SI with the highest
  97. * dependency_level it depends on. When SG is requested to assign the workload
  98. * on a certain dependency level, it requests all SI objects on that level to
  99. * activate (all) SI-assignments that during step <1> has been requested to
  100. * assume the active HA state.
  101. *
  102. * SG contains the following state machines:
  103. * - administrative state machine (ADSM) (NOT IN THIS RELEASE)
  104. * - availability control state machine (ACSM)
  105. *
  106. * The availability control state machine contains two states and one of them
  107. * is composite. Being a composite state means that it contains substates.
  108. * The states are:
  109. * - IDLE (non composite state)
  110. * - MANAGING_SG (composite state)
  111. * MANAGING_SG is entered at several different events which has in common
  112. * the need to set up or change the assignment of SIs to SUs. Only one such
  113. * event can be handled at the time. If new events occur while one event is
  114. * being handled then the new event is saved and will be handled after the
  115. * handling of the first event is ready (return to IDLE state has been done).
  116. * MANAGING_SG handles the following events:
  117. * - start (requests SG to order SU to instantiate all SUs in SG and waits
  118. * for SU to indicate presence state change reports from the SUs and
  119. * finally responds 'started' to the requester)
  120. * - assign (requests SG to assign SIs to SUs according to pre-configured
  121. * rules (if not already done) and transfer the HA state of
  122. * the SIs on the requested SI dependency level. Then SG waits for
  123. * confirmation that the HA state has been succesfully set and
  124. * finally responds 'assigned' to the reqeuster)
  125. * - auto_adjust (this event indicates that the auto-adjust probation timer has
  126. * expired and that SG should evaluate current assignments of
  127. * SIs to SUs and if needed remove current assignments and
  128. * create new according to what is specified in paragraph
  129. * 3.7.1.2)
  130. * - failover_comp (requests SG to failover a specific component according to
  131. * the procedure described in paragraph 3.12.1.3)
  132. * - failover_su (requests SG to failover a specific SU according to the
  133. * procedure described in paragraph 3.12.1.3 and 3.12.1.4)
  134. * - switchover_node (requests SG to execute the recovery actions described
  135. * in 3.12.1.3 and respond to the requester when recovery
  136. * is completed)
  137. * - failover_node (requests SG to execute the recovery actions described
  138. * in 3.12.1.3 and respond to the requester when recovery is
  139. * completed)
  140. *
  141. */
  142. #include <stdlib.h>
  143. #include <errno.h>
  144. #include "amf.h"
  145. #include "print.h"
  146. #include "main.h"
  147. #include "util.h"
  148. static void acsm_enter_activating_standby (struct amf_sg *sg);
  149. static void delete_si_assignments_in_scope (struct amf_sg *sg);
  150. static void acsm_enter_repairing_su (struct amf_sg *sg);
  151. static void standby_su_activated_cbfn (
  152. struct amf_si_assignment *si_assignment, int result);
  153. static void dependent_si_deactivated_cbfn (
  154. struct amf_si_assignment *si_assignment, int result);
  155. static const char *sg_recovery_type_text[] = {
  156. "Unknown",
  157. "FailoverSU",
  158. "FailoverNode"
  159. };
  160. static void return_to_idle (struct amf_sg *sg)
  161. {
  162. SaNameT dn;
  163. ENTER ("sg: %s state: %d", sg->name.value,sg->avail_state);
  164. sg->avail_state = SG_AC_Idle;
  165. if (sg->recovery_scope.recovery_type != 0) {
  166. switch (sg->recovery_scope.recovery_type) {
  167. case SG_RT_FailoverSU:
  168. assert (sg->recovery_scope.sus[0] != NULL);
  169. amf_su_dn_make (sg->recovery_scope.sus[0], &dn);
  170. log_printf (
  171. LOG_NOTICE, "'%s' %s recovery action finished",
  172. dn.value,
  173. sg_recovery_type_text[sg->recovery_scope.recovery_type]);
  174. break;
  175. case SG_RT_FailoverNode:
  176. amf_node_sg_failed_over (sg->recovery_scope.node, sg);
  177. log_printf (
  178. LOG_NOTICE, "'%s for %s' recovery action finished",
  179. sg_recovery_type_text[sg->recovery_scope.recovery_type],
  180. sg->name.value);
  181. break;
  182. default:
  183. log_printf (
  184. LOG_NOTICE, "'%s' recovery action finished",
  185. sg_recovery_type_text[0]);
  186. break;
  187. }
  188. }
  189. if (sg->recovery_scope.sus != NULL) {
  190. free ((void *)sg->recovery_scope.sus);
  191. }
  192. if (sg->recovery_scope.sis != NULL) {
  193. free ((void *)sg->recovery_scope.sis);
  194. }
  195. memset (&sg->recovery_scope, 0, sizeof (struct sg_recovery_scope));
  196. sg->node_to_start = NULL;
  197. }
  198. static int su_instantiated_count (struct amf_sg *sg)
  199. {
  200. int cnt = 0;
  201. struct amf_su *su;
  202. for (su = sg->su_head; su != NULL; su = su->next) {
  203. if (su->saAmfSUPresenceState == SA_AMF_PRESENCE_INSTANTIATED)
  204. cnt++;
  205. }
  206. return cnt;
  207. }
  208. static int has_any_su_in_scope_active_workload (struct amf_sg *sg)
  209. {
  210. struct amf_su **sus= sg->recovery_scope.sus;
  211. struct amf_si_assignment *si_assignment;
  212. while (*sus != NULL) {
  213. si_assignment = amf_su_get_next_si_assignment (*sus, NULL);
  214. while (si_assignment != NULL) {
  215. if (si_assignment->saAmfSISUHAState != SA_AMF_HA_ACTIVE) {
  216. break;
  217. }
  218. si_assignment = amf_su_get_next_si_assignment (
  219. *sus, si_assignment);
  220. }
  221. if (si_assignment != NULL) {
  222. break;
  223. }
  224. sus++;
  225. }
  226. return(*sus == NULL);
  227. }
  228. static int is_standby_for_non_active_si_in_scope (struct amf_sg *sg)
  229. {
  230. struct amf_si **sis= sg->recovery_scope.sis;
  231. struct amf_si_assignment *si_assignment;
  232. /*
  233. * Check if there is any si in the scope which has no active assignment
  234. * and at least one standby assignment.
  235. */
  236. while (*sis != NULL) {
  237. si_assignment = (*sis)->assigned_sis;
  238. while (si_assignment != NULL) {
  239. if (si_assignment->saAmfSISUHAState == SA_AMF_HA_ACTIVE) {
  240. break;
  241. }
  242. si_assignment = si_assignment->next;
  243. }
  244. if (si_assignment == NULL) {
  245. /* There is no ACTIVE assignment ..*/
  246. si_assignment = (*sis)->assigned_sis;
  247. while (si_assignment != NULL) {
  248. if (si_assignment->saAmfSISUHAState == SA_AMF_HA_STANDBY) {
  249. break;
  250. }
  251. si_assignment = si_assignment->next;
  252. }
  253. if (si_assignment != NULL) {
  254. /* .. and one STANDBY assignment*/
  255. break;
  256. }
  257. }
  258. sis++;
  259. }
  260. return(*sis != NULL);
  261. }
  262. static void acsm_enter_terminating_suspected (struct amf_sg *sg)
  263. {
  264. struct amf_su **sus= sg->recovery_scope.sus;
  265. sg->avail_state = SG_AC_TerminatingSuspected;
  266. /*
  267. * Terminate suspected SU(s)
  268. */
  269. while (*sus != 0) {
  270. amf_su_terminate (*sus);
  271. sus++;
  272. }
  273. }
  274. /**
  275. * Callback function used by SI when there is no dependent SI to
  276. * deactivate.
  277. * @param sg
  278. */
  279. static void dependent_si_deactivated_cbfn2 (struct amf_sg *sg)
  280. {
  281. struct amf_su **sus = sg->recovery_scope.sus;
  282. ENTER("'%s'", sg->name.value);
  283. /* Select next state depending on if some SU in the scope is
  284. * needs to be terminated.
  285. */
  286. while (*sus != NULL) {
  287. ENTER("SU %s pr_state='%d'",(*sus)->name.value,
  288. (*sus)->saAmfSUPresenceState);
  289. if (((*sus)->saAmfSUPresenceState ==
  290. SA_AMF_PRESENCE_UNINSTANTIATED) ||
  291. ((*sus)->saAmfSUPresenceState ==
  292. SA_AMF_PRESENCE_TERMINATION_FAILED) ||
  293. ((*sus)->saAmfSUPresenceState ==
  294. SA_AMF_PRESENCE_INSTANTIATION_FAILED)) {
  295. sus++;
  296. continue;
  297. }
  298. break;
  299. }
  300. if (*sus != NULL) {
  301. acsm_enter_terminating_suspected (sg);
  302. } else {
  303. delete_si_assignments_in_scope(sg);
  304. acsm_enter_activating_standby (sg);
  305. }
  306. }
  307. static void timer_function_dependent_si_deactivated2 (void *sg)
  308. {
  309. ENTER ("");
  310. dependent_si_deactivated_cbfn2 (sg);
  311. }
  312. static struct amf_si *si_get_dependent (struct amf_si *si)
  313. {
  314. struct amf_si *tmp_si = NULL;
  315. ENTER("'%p'",si->depends_on);
  316. if (si->depends_on != NULL) {
  317. if (si->depends_on->name.length < SA_MAX_NAME_LENGTH) {
  318. si->depends_on->name.value[si->depends_on->name.length] = '\0';
  319. }
  320. SaNameT res_arr[2];
  321. int is_match;
  322. is_match = sa_amf_grep ((char*)si->depends_on->name.value,
  323. "safDepend=.*,safSi=(.*),safApp=.*",
  324. 2, res_arr);
  325. if (is_match) {
  326. tmp_si = amf_si_find (si->application, (char*)res_arr[1].value);
  327. } else {
  328. log_printf (LOG_LEVEL_ERROR, "distinguished name for "
  329. "amf_si_depedency failed\n");
  330. openais_exit_error (AIS_DONE_FATAL_ERR);
  331. }
  332. }
  333. return tmp_si;
  334. }
  335. struct amf_si *amf_dependent_get_next (struct amf_si *si,
  336. struct amf_si *si_iter)
  337. {
  338. struct amf_si *tmp_si;
  339. struct amf_application *application;
  340. ENTER("");
  341. if (si_iter == NULL) {
  342. assert(amf_cluster != NULL);
  343. application = amf_cluster->application_head;
  344. assert(application != NULL);
  345. tmp_si = application->si_head;
  346. } else {
  347. tmp_si = si_iter->next;
  348. if (tmp_si == NULL) {
  349. application = si->application->next;
  350. if (application == NULL) {
  351. goto out;
  352. }
  353. }
  354. }
  355. for (; tmp_si != NULL; tmp_si = tmp_si->next) {
  356. struct amf_si *depends_on_si = si_get_dependent (tmp_si);
  357. while (depends_on_si != NULL) {
  358. if (depends_on_si == si) {
  359. goto out;
  360. }
  361. depends_on_si = depends_on_si->next;
  362. }
  363. }
  364. out:
  365. return tmp_si;
  366. }
  367. static void acsm_enter_deactivating_dependent_workload (struct amf_sg *sg)
  368. {
  369. struct amf_si **sis= sg->recovery_scope.sis;
  370. struct amf_si_assignment *si_assignment;
  371. int callback_pending = 0;
  372. sg->avail_state = SG_AC_DeactivatingDependantWorkload;
  373. ENTER("'%s'",sg->name.value);
  374. /*
  375. * For each SI in the recovery scope, find all active assignments
  376. * and request them to be deactivated.
  377. */
  378. while (*sis != NULL) {
  379. struct amf_si *dependent_si;
  380. struct amf_si *si = *sis;
  381. si_assignment = si->assigned_sis;
  382. dependent_si = amf_dependent_get_next (si, NULL);
  383. while (dependent_si != NULL) {
  384. si_assignment = dependent_si->assigned_sis;
  385. while (si_assignment != NULL) {
  386. if (si_assignment->saAmfSISUHAState == SA_AMF_HA_ACTIVE) {
  387. si_assignment->requested_ha_state = SA_AMF_HA_QUIESCED;
  388. callback_pending = 1;
  389. amf_si_ha_state_assume (
  390. si_assignment, dependent_si_deactivated_cbfn);
  391. }
  392. si_assignment = si_assignment->next;
  393. }
  394. dependent_si = amf_dependent_get_next (si, dependent_si);
  395. }
  396. sis++;
  397. }
  398. if (callback_pending == 0) {
  399. poll_timer_handle handle;
  400. ENTER("");
  401. poll_timer_add (aisexec_poll_handle, 0, sg,
  402. timer_function_dependent_si_deactivated2, &handle);
  403. }
  404. }
  405. /**
  406. * Enter function for state SG_AC_ActivatingStandby. It activates
  407. * one STANDBY assignment for each SI in the recovery scope.
  408. * @param sg
  409. */
  410. static void acsm_enter_activating_standby (struct amf_sg *sg)
  411. {
  412. struct amf_si **sis= sg->recovery_scope.sis;
  413. struct amf_si_assignment *si_assignment;
  414. int is_no_standby_activated = 1;
  415. ENTER("'%s'",sg->name.value);
  416. sg->avail_state = SG_AC_ActivatingStandby;
  417. /*
  418. * For each SI in the recovery scope, find one standby
  419. * SI assignment and activate it.
  420. */
  421. while (*sis != NULL) {
  422. si_assignment = (*sis)->assigned_sis;
  423. while (si_assignment != NULL) {
  424. if (si_assignment->saAmfSISUHAState == SA_AMF_HA_STANDBY) {
  425. si_assignment->requested_ha_state = SA_AMF_HA_ACTIVE;
  426. amf_si_ha_state_assume (
  427. si_assignment, standby_su_activated_cbfn);
  428. is_no_standby_activated = 0;
  429. break;
  430. }
  431. si_assignment = si_assignment->next;
  432. }
  433. sis++;
  434. }
  435. if (is_no_standby_activated) {
  436. sg->avail_state = SG_AC_AssigningStandbyToSpare;
  437. acsm_enter_repairing_su (sg);
  438. }
  439. }
  440. static void acsm_enter_repairing_su (struct amf_sg *sg)
  441. {
  442. struct amf_su **sus= sg->recovery_scope.sus;
  443. ENTER("'%s'",sg->name.value);
  444. sg->avail_state = SG_AC_ReparingSu;
  445. int is_any_su_instantiated = 0;
  446. /*
  447. * Instantiate SUs in current recovery scope until the configured
  448. * preference is fulfiled.
  449. */
  450. while (*sus != NULL) {
  451. if (su_instantiated_count ((*sus)->sg) <
  452. (*sus)->sg->saAmfSGNumPrefInserviceSUs) {
  453. struct amf_node *node = amf_node_find(&((*sus)->saAmfSUHostedByNode));
  454. if (node == NULL) {
  455. log_printf (LOG_LEVEL_ERROR, "no node to hosted on su found"
  456. "amf_si_depedency failed\n");
  457. openais_exit_error (AIS_DONE_FATAL_ERR);
  458. }
  459. if (node->saAmfNodeOperState == SA_AMF_OPERATIONAL_ENABLED) {
  460. /* node is synchronized */
  461. is_any_su_instantiated = 1;
  462. amf_su_instantiate ((*sus));
  463. }
  464. }
  465. sus++;
  466. }
  467. if (is_any_su_instantiated == 0) {
  468. return_to_idle (sg);
  469. }
  470. }
  471. /**
  472. * Checks if the si pointed out is already in the scope.
  473. * @param sg
  474. * @param si
  475. */
  476. static int is_si_in_scope(struct amf_sg *sg, struct amf_si *si)
  477. {
  478. struct amf_si **tmp_sis= sg->recovery_scope.sis;
  479. while (*tmp_sis != NULL) {
  480. if (*tmp_sis == si) {
  481. break;
  482. }
  483. tmp_sis++;
  484. }
  485. return(*tmp_sis == si);
  486. }
  487. /**
  488. * Adds the si pointed out to the scope.
  489. * @param sg
  490. * @param si
  491. */
  492. static void add_si_to_scope ( struct amf_sg *sg, struct amf_si *si)
  493. {
  494. int number_of_si = 2; /* It shall be at least two */
  495. struct amf_si **tmp_sis= sg->recovery_scope.sis;
  496. ENTER ("'%s'", si->name.value);
  497. while (*tmp_sis != NULL) {
  498. number_of_si++;
  499. tmp_sis++;
  500. }
  501. sg->recovery_scope.sis = (struct amf_si **)
  502. realloc((void *)sg->recovery_scope.sis,
  503. sizeof (struct amf_si *)*number_of_si);
  504. assert (sg->recovery_scope.sis != NULL);
  505. tmp_sis= sg->recovery_scope.sis;
  506. while (*tmp_sis != NULL) {
  507. tmp_sis++;
  508. }
  509. *tmp_sis = si;
  510. *(++tmp_sis) = NULL;
  511. }
  512. /**
  513. * Adds the ssu pointed out to the scope.
  514. * @param sg
  515. * @param su
  516. */
  517. static void add_su_to_scope (struct amf_sg *sg, struct amf_su *su)
  518. {
  519. int number_of_su = 2; /* It shall be at least two */
  520. struct amf_su **tmp_sus= sg->recovery_scope.sus;
  521. ENTER ("'%s'", su->name.value);
  522. while (*tmp_sus != NULL) {
  523. number_of_su++;
  524. tmp_sus++;
  525. }
  526. sg->recovery_scope.sus = (struct amf_su **)
  527. realloc((void *)sg->recovery_scope.sus,
  528. sizeof (struct amf_su *)*number_of_su);
  529. assert (sg->recovery_scope.sus != NULL);
  530. tmp_sus= sg->recovery_scope.sus;
  531. while (*tmp_sus != NULL) {
  532. tmp_sus++;
  533. }
  534. *tmp_sus = su;
  535. *(++tmp_sus) = NULL;
  536. }
  537. /**
  538. * Set recovery scope for failover SU.
  539. * @param sg
  540. * @param su
  541. */
  542. static void set_scope_for_failover_su (struct amf_sg *sg, struct amf_su *su)
  543. {
  544. struct amf_si_assignment *si_assignment;
  545. struct amf_si **sis;
  546. struct amf_su **sus;
  547. SaNameT dn;
  548. sg->recovery_scope.recovery_type = SG_RT_FailoverSU;
  549. sg->recovery_scope.node = NULL;
  550. sg->recovery_scope.comp = NULL;
  551. sg->recovery_scope.sus = (struct amf_su **)
  552. calloc (2, sizeof (struct amf_su *));
  553. sg->recovery_scope.sis = (struct amf_si **)
  554. calloc (1, sizeof (struct amf_si *));
  555. assert ((sg->recovery_scope.sus != NULL) &&
  556. (sg->recovery_scope.sis != NULL));
  557. sg->recovery_scope.sus[0] = su;
  558. amf_su_dn_make (sg->recovery_scope.sus[0], &dn);
  559. log_printf (
  560. LOG_NOTICE, "'%s' for %s recovery action started",
  561. sg_recovery_type_text[sg->recovery_scope.recovery_type],
  562. dn.value);
  563. si_assignment = amf_su_get_next_si_assignment (su, NULL);
  564. while (si_assignment != NULL) {
  565. if (is_si_in_scope(sg, si_assignment->si) == 0) {
  566. add_si_to_scope(sg,si_assignment->si );
  567. }
  568. si_assignment = amf_su_get_next_si_assignment (su, si_assignment);
  569. }
  570. sus = sg->recovery_scope.sus;
  571. dprintf("The following sus are within the scope:\n");
  572. while (*sus != NULL) {
  573. dprintf("%s\n", (*sus)->name.value);
  574. sus++;
  575. }
  576. sis= sg->recovery_scope.sis;
  577. dprintf("The following sis are within the scope:\n");
  578. while (*sis != NULL) {
  579. dprintf("%s\n", (*sis)->name.value);
  580. sis++;
  581. }
  582. }
  583. static void set_scope_for_failover_node (struct amf_sg *sg, struct amf_node *node)
  584. {
  585. struct amf_si_assignment *si_assignment;
  586. struct amf_si **sis;
  587. struct amf_su **sus;
  588. struct amf_su *su;
  589. ENTER ("'%s'", node->name.value);
  590. sg->recovery_scope.recovery_type = SG_RT_FailoverNode;
  591. sg->recovery_scope.node = node;
  592. sg->recovery_scope.comp = NULL;
  593. sg->recovery_scope.sus = (struct amf_su **)
  594. calloc (1, sizeof (struct amf_su *));
  595. sg->recovery_scope.sis = (struct amf_si **)
  596. calloc (1, sizeof (struct amf_si *));
  597. log_printf (
  598. LOG_NOTICE, "'%s' for node %s recovery action started",
  599. sg_recovery_type_text[sg->recovery_scope.recovery_type],
  600. node->name.value);
  601. assert ((sg->recovery_scope.sus != NULL) &&
  602. (sg->recovery_scope.sis != NULL));
  603. for (su = sg->su_head; su != NULL; su = su->next) {
  604. if (name_match (&node->name, &su->saAmfSUHostedByNode)) {
  605. add_su_to_scope (sg, su);
  606. }
  607. }
  608. sus = sg->recovery_scope.sus;
  609. while (*sus != 0) {
  610. su = *sus;
  611. si_assignment = amf_su_get_next_si_assignment (su, NULL);
  612. while (si_assignment != NULL) {
  613. if (is_si_in_scope(sg, si_assignment->si) == 0) {
  614. add_si_to_scope(sg, si_assignment->si );
  615. }
  616. si_assignment = amf_su_get_next_si_assignment (su, si_assignment);
  617. }
  618. sus++;
  619. }
  620. sus = sg->recovery_scope.sus;
  621. dprintf("The following sus are within the scope:\n");
  622. while (*sus != NULL) {
  623. dprintf("%s\n", (*sus)->name.value);
  624. sus++;
  625. }
  626. sis = sg->recovery_scope.sis;
  627. dprintf("The following sis are within the scope:\n");
  628. while (*sis != NULL) {
  629. dprintf("%s\n", (*sis)->name.value);
  630. sis++;
  631. }
  632. }
  633. /**
  634. * Delete all SI assignments and all CSI assignments
  635. * by requesting all contained components.
  636. * @param su
  637. */
  638. static void delete_si_assignments (struct amf_su *su)
  639. {
  640. struct amf_csi *csi;
  641. struct amf_si *si;
  642. struct amf_si_assignment *si_assignment;
  643. struct amf_si_assignment **prev;
  644. ENTER ("'%s'", su->name.value);
  645. for (si = su->sg->application->si_head; si != NULL; si = si->next) {
  646. prev = &si->assigned_sis;
  647. if (!name_match (&si->saAmfSIProtectedbySG, &su->sg->name)) {
  648. continue;
  649. }
  650. for (csi = si->csi_head; csi != NULL; csi = csi->next) {
  651. amf_csi_delete_assignments (csi, su);
  652. }
  653. for (si_assignment = si->assigned_sis; si_assignment != NULL;
  654. si_assignment = si_assignment->next) {
  655. if (si_assignment->su == su) {
  656. struct amf_si_assignment *tmp = si_assignment;
  657. *prev = si_assignment->next;
  658. dprintf ("SI assignment %s unlinked", tmp->name.value);
  659. free (tmp);
  660. } else {
  661. prev = &si_assignment->next;
  662. }
  663. }
  664. }
  665. }
  666. /**
  667. * Delete all SI assignments and all CSI assignments in current
  668. * recovery scope.
  669. * @param sg
  670. */
  671. static void delete_si_assignments_in_scope (struct amf_sg *sg)
  672. {
  673. struct amf_su **sus= sg->recovery_scope.sus;
  674. while (*sus != NULL) {
  675. delete_si_assignments (*sus);
  676. sus++;
  677. }
  678. }
  679. /**
  680. * Callback function used by SI when an SI has been deactivated.
  681. * @param si_assignment
  682. * @param result
  683. */
  684. static void dependent_si_deactivated_cbfn (
  685. struct amf_si_assignment *si_assignment, int result)
  686. {
  687. struct amf_sg *sg = si_assignment->su->sg;
  688. struct amf_su **sus = sg->recovery_scope.sus;
  689. struct amf_su *su;
  690. ENTER ("'%s', %d", si_assignment->si->name.value, result);
  691. /*
  692. * If all SI assignments for all SUs in the SG are not pending,
  693. * goto next state (TerminatingSuspected).
  694. */
  695. for (su = sg->su_head ; su != NULL; su = su->next) {
  696. struct amf_si_assignment *si_assignment;
  697. si_assignment = amf_su_get_next_si_assignment(su, NULL);
  698. while (si_assignment != NULL) {
  699. if (si_assignment->saAmfSISUHAState !=
  700. si_assignment->requested_ha_state) {
  701. goto still_wating;
  702. }
  703. si_assignment = amf_su_get_next_si_assignment(su, si_assignment);
  704. }
  705. }
  706. still_wating:
  707. if (su == NULL) {
  708. sus = si_assignment->su->sg->recovery_scope.sus;
  709. /* Select next state depending on if some SU in the scope is
  710. * needs to be terminated.
  711. */
  712. while (*sus != NULL) {
  713. if (((*sus)->saAmfSUPresenceState !=
  714. SA_AMF_PRESENCE_UNINSTANTIATED) &&
  715. ((*sus)->saAmfSUPresenceState !=
  716. SA_AMF_PRESENCE_TERMINATION_FAILED) &&
  717. ((*sus)->saAmfSUPresenceState !=
  718. SA_AMF_PRESENCE_INSTANTIATION_FAILED)) {
  719. break;
  720. }
  721. sus++;
  722. }
  723. if (*sus != NULL) {
  724. acsm_enter_terminating_suspected (sg);
  725. } else {
  726. delete_si_assignments_in_scope(sg);
  727. acsm_enter_activating_standby (sg);
  728. }
  729. }
  730. LEAVE("");
  731. }
  732. static void standby_su_activated_cbfn (
  733. struct amf_si_assignment *si_assignment, int result)
  734. {
  735. struct amf_su **sus= si_assignment->su->sg->recovery_scope.sus;
  736. struct amf_si **sis= si_assignment->su->sg->recovery_scope.sis;
  737. ENTER ("'%s', %d", si_assignment->si->name.value, result);
  738. /*
  739. * If all SI assignments for all SIs in the scope are activated, goto next
  740. * state.
  741. */
  742. while (*sis != NULL) {
  743. if ((*sis)->assigned_sis != NULL &&
  744. (*sis)->assigned_sis->saAmfSISUHAState != SA_AMF_HA_ACTIVE) {
  745. break;
  746. }
  747. sis++;
  748. }
  749. if (*sis == NULL) {
  750. /*
  751. * TODO: create SI assignment to spare and assign them
  752. */
  753. (*sus)->sg->avail_state = SG_AC_AssigningStandbyToSpare;
  754. acsm_enter_repairing_su ((*sus)->sg);
  755. }
  756. }
  757. static void assign_si_assumed_cbfn (
  758. struct amf_si_assignment *si_assignment, int result)
  759. {
  760. struct amf_si_assignment *tmp_si_assignment;
  761. struct amf_si *si;
  762. struct amf_sg *sg = si_assignment->su->sg;
  763. int si_assignment_cnt = 0;
  764. int confirmed_assignments = 0;
  765. ENTER ("'%s', %d", si_assignment->si->name.value, result);
  766. /*
  767. * Report to application when all SIs that this SG protects
  768. * has been assigned or go back to idle state if not cluster
  769. * start.
  770. */
  771. for (si = sg->application->si_head; si != NULL; si = si->next) {
  772. if (name_match (&si->saAmfSIProtectedbySG, &sg->name)) {
  773. for (tmp_si_assignment = si->assigned_sis;
  774. tmp_si_assignment != NULL;
  775. tmp_si_assignment = tmp_si_assignment->next) {
  776. si_assignment_cnt++;
  777. if (tmp_si_assignment->requested_ha_state ==
  778. tmp_si_assignment->saAmfSISUHAState) {
  779. confirmed_assignments++;
  780. }
  781. }
  782. }
  783. }
  784. assert (confirmed_assignments != 0);
  785. switch (sg->avail_state) {
  786. case SG_AC_AssigningOnRequest:
  787. if (si_assignment_cnt == confirmed_assignments) {
  788. return_to_idle (sg);
  789. amf_application_sg_assigned (sg->application, sg);
  790. } else {
  791. dprintf ("%d, %d", si_assignment_cnt, confirmed_assignments);
  792. }
  793. break;
  794. case SG_AC_AssigningStandBy:
  795. {
  796. if (si_assignment_cnt == confirmed_assignments) {
  797. return_to_idle (sg);
  798. }
  799. break;
  800. }
  801. default:
  802. dprintf ("%d, %d, %d", sg->avail_state, si_assignment_cnt,
  803. confirmed_assignments);
  804. amf_runtime_attributes_print (amf_cluster);
  805. assert (0);
  806. break;
  807. }
  808. }
  809. static inline int div_round (int a, int b)
  810. {
  811. int res;
  812. assert (b != 0);
  813. res = a / b;
  814. if ((a % b) != 0)
  815. res++;
  816. return res;
  817. }
  818. #ifdef COMPILE_OUT
  819. static int all_su_has_presence_state (
  820. struct amf_sg *sg, struct amf_node *node_to_start,
  821. SaAmfPresenceStateT state)
  822. {
  823. struct amf_su *su;
  824. int all_set = 1;
  825. for (su = sg->su_head; su != NULL; su = su->next) {
  826. if (su->saAmfSUPresenceState != state) {
  827. if (node_to_start == NULL) {
  828. all_set = 0;
  829. break;
  830. } else {
  831. if (name_match(&node_to_start->name,
  832. &su->saAmfSUHostedByNode)) {
  833. all_set = 0;
  834. break;
  835. }
  836. }
  837. }
  838. }
  839. return all_set;
  840. }
  841. #endif
  842. static int no_su_has_presence_state (
  843. struct amf_sg *sg, struct amf_node *node_to_start,
  844. SaAmfPresenceStateT state)
  845. {
  846. struct amf_su *su;
  847. int no_su_has_presence_state = 1;
  848. for (su = sg->su_head; su != NULL; su = su->next) {
  849. if (su->saAmfSUPresenceState == state) {
  850. if (node_to_start == NULL) {
  851. no_su_has_presence_state = 0;
  852. break;
  853. } else {
  854. if (name_match(&node_to_start->name,
  855. &su->saAmfSUHostedByNode)) {
  856. no_su_has_presence_state = 0;
  857. break;
  858. }
  859. }
  860. }
  861. }
  862. return no_su_has_presence_state;
  863. }
  864. static int all_su_in_scope_has_presence_state (
  865. struct amf_sg *sg, SaAmfPresenceStateT state)
  866. {
  867. struct amf_su **sus= sg->recovery_scope.sus;
  868. while (*sus != NULL) {
  869. if ((*sus)->saAmfSUPresenceState != state) {
  870. break;
  871. }
  872. sus++;
  873. }
  874. return(*sus == NULL);
  875. }
  876. /**
  877. * Get number of SIs protected by the specified SG.
  878. * @param sg
  879. *
  880. * @return int
  881. */
  882. static int sg_si_count_get (struct amf_sg *sg)
  883. {
  884. struct amf_si *si;
  885. int cnt = 0;
  886. for (si = sg->application->si_head; si != NULL; si = si->next) {
  887. if (name_match (&si->saAmfSIProtectedbySG, &sg->name)) {
  888. cnt += 1;
  889. }
  890. }
  891. return(cnt);
  892. }
  893. int amf_si_get_saAmfSINumReqActiveAssignments(struct amf_si *si)
  894. {
  895. struct amf_si_assignment *si_assignment = si->assigned_sis;
  896. int number_of_req_active_assignments = 0;
  897. for (; si_assignment != NULL; si_assignment = si_assignment->next) {
  898. if (si_assignment->requested_ha_state == SA_AMF_HA_ACTIVE) {
  899. number_of_req_active_assignments++;
  900. }
  901. }
  902. return number_of_req_active_assignments;
  903. }
  904. int amf_si_get_saAmfSINumReqStandbyAssignments(struct amf_si *si)
  905. {
  906. struct amf_si_assignment *si_assignment = si->assigned_sis;
  907. int number_of_req_active_assignments = 0;
  908. for (; si_assignment != NULL; si_assignment = si_assignment->next) {
  909. if (si_assignment->requested_ha_state == SA_AMF_HA_STANDBY) {
  910. number_of_req_active_assignments++;
  911. }
  912. }
  913. return number_of_req_active_assignments;
  914. }
  915. static int sg_assign_nm_active (struct amf_sg *sg, int su_active_assign)
  916. {
  917. struct amf_su *su;
  918. struct amf_si *si;
  919. int assigned = 0;
  920. int assign_to_su = 0;
  921. int total_assigned = 0;
  922. int si_left;
  923. int si_total;
  924. int su_left_to_assign = su_active_assign;
  925. si_total = sg_si_count_get (sg);
  926. si_left = si_total;
  927. assign_to_su = div_round (si_left, su_active_assign);
  928. if (assign_to_su > sg->saAmfSGMaxActiveSIsperSUs) {
  929. assign_to_su = sg->saAmfSGMaxActiveSIsperSUs;
  930. }
  931. su = sg->su_head;
  932. while (su != NULL && su_left_to_assign > 0) {
  933. if (amf_su_get_saAmfSUReadinessState (su) !=
  934. SA_AMF_READINESS_IN_SERVICE ||
  935. amf_su_get_saAmfSUNumCurrActiveSIs (su) ==
  936. assign_to_su ||
  937. amf_su_get_saAmfSUNumCurrStandbySIs (su) > 0) {
  938. su = su->next;
  939. continue; /* Not in service */
  940. }
  941. si = sg->application->si_head;
  942. assigned = 0;
  943. assign_to_su = div_round (si_left, su_left_to_assign);
  944. if (assign_to_su > sg->saAmfSGMaxActiveSIsperSUs) {
  945. assign_to_su = sg->saAmfSGMaxActiveSIsperSUs;
  946. }
  947. while (si != NULL) {
  948. if (name_match (&si->saAmfSIProtectedbySG, &sg->name) &&
  949. assigned < assign_to_su &&
  950. amf_si_get_saAmfSINumReqActiveAssignments(si) == 0) {
  951. assigned += 1;
  952. total_assigned += 1;
  953. amf_su_assign_si (su, si, SA_AMF_HA_ACTIVE);
  954. }
  955. si = si->next;
  956. }
  957. su = su->next;
  958. su_left_to_assign -= 1;
  959. si_left -= assigned;
  960. dprintf (" su_left_to_assign =%d, si_left=%d\n",
  961. su_left_to_assign, si_left);
  962. }
  963. assert (total_assigned <= si_total);
  964. if (total_assigned == 0) {
  965. dprintf ("Info: No SIs assigned");
  966. }
  967. LEAVE();
  968. return total_assigned;
  969. }
  970. static int sg_assign_nm_standby (struct amf_sg *sg, int su_standby_assign)
  971. {
  972. struct amf_su *su;
  973. struct amf_si *si;
  974. int assigned = 0;
  975. int assign_to_su = 0;
  976. int total_assigned = 0;
  977. int si_left;
  978. int si_total;
  979. int su_left_to_assign = su_standby_assign;
  980. ENTER ("'%s'", sg->name.value);
  981. if (su_standby_assign == 0) {
  982. return 0;
  983. }
  984. si_total = sg_si_count_get (sg);
  985. si_left = si_total;
  986. assign_to_su = div_round (si_left, su_standby_assign);
  987. if (assign_to_su > sg->saAmfSGMaxStandbySIsperSUs) {
  988. assign_to_su = sg->saAmfSGMaxStandbySIsperSUs;
  989. }
  990. su = sg->su_head;
  991. while (su != NULL && su_left_to_assign > 0) {
  992. if (amf_su_get_saAmfSUReadinessState (su) !=
  993. SA_AMF_READINESS_IN_SERVICE ||
  994. amf_su_get_saAmfSUNumCurrActiveSIs (su) > 0 ||
  995. amf_su_get_saAmfSUNumCurrStandbySIs (su) ==
  996. assign_to_su) {
  997. su = su->next;
  998. continue; /* Not available for assignment */
  999. }
  1000. si = sg->application->si_head;
  1001. assigned = 0;
  1002. assign_to_su = div_round (si_left, su_left_to_assign);
  1003. if (assign_to_su > sg->saAmfSGMaxStandbySIsperSUs) {
  1004. assign_to_su = sg->saAmfSGMaxStandbySIsperSUs;
  1005. }
  1006. while (si != NULL) {
  1007. if (name_match (&si->saAmfSIProtectedbySG, &sg->name) &&
  1008. assigned < assign_to_su &&
  1009. amf_si_get_saAmfSINumReqStandbyAssignments (si) == 0) {
  1010. assigned += 1;
  1011. total_assigned += 1;
  1012. amf_su_assign_si (su, si, SA_AMF_HA_STANDBY);
  1013. }
  1014. si = si->next;
  1015. }
  1016. su_left_to_assign -= 1;
  1017. si_left -= assigned;
  1018. dprintf (" su_left_to_assign =%d, si_left=%d\n",
  1019. su_left_to_assign, si_left);
  1020. su = su->next;
  1021. }
  1022. assert (total_assigned <= si_total);
  1023. if (total_assigned == 0) {
  1024. dprintf ("Info: No SIs assigned!");
  1025. }
  1026. return total_assigned;
  1027. }
  1028. static int su_inservice_count_get (struct amf_sg *sg)
  1029. {
  1030. struct amf_su *su;
  1031. int answer = 0;
  1032. for (su = sg->su_head; su != NULL; su = su->next) {
  1033. if (amf_su_get_saAmfSUReadinessState (su) ==
  1034. SA_AMF_READINESS_IN_SERVICE) {
  1035. answer += 1;
  1036. }
  1037. }
  1038. return(answer);
  1039. }
  1040. /**
  1041. * TODO: dependency_level not used, hard coded
  1042. * @param sg
  1043. * @param dependency_level
  1044. */
  1045. static int assign_si (struct amf_sg *sg, int dependency_level)
  1046. {
  1047. int active_sus_needed = 0;
  1048. int standby_sus_needed = 0;
  1049. int inservice_count;
  1050. int su_active_assign;
  1051. int su_standby_assign;
  1052. int su_spare_assign;
  1053. int assigned = 0;
  1054. ENTER ("'%s'", sg->name.value);
  1055. /**
  1056. * Phase 1: Calculate assignments and create all runtime objects in
  1057. * information model. Do not do the actual assignment, done in
  1058. * phase 2.
  1059. */
  1060. /**
  1061. * Calculate number of SUs to assign to active or standby state
  1062. */
  1063. inservice_count = su_inservice_count_get (sg);
  1064. if (sg->saAmfSGNumPrefActiveSUs > 0) {
  1065. active_sus_needed = div_round (
  1066. sg_si_count_get (sg),
  1067. sg->saAmfSGMaxActiveSIsperSUs);
  1068. } else {
  1069. log_printf (LOG_LEVEL_ERROR, "ERROR: saAmfSGNumPrefActiveSUs == 0 !!");
  1070. openais_exit_error (AIS_DONE_FATAL_ERR);
  1071. }
  1072. if (sg->saAmfSGNumPrefStandbySUs > 0) {
  1073. standby_sus_needed = div_round (
  1074. sg_si_count_get (sg),
  1075. sg->saAmfSGMaxStandbySIsperSUs);
  1076. } else {
  1077. log_printf (LOG_LEVEL_ERROR, "ERROR: saAmfSGNumPrefStandbySUs == 0 !!");
  1078. openais_exit_error (AIS_DONE_FATAL_ERR);
  1079. }
  1080. dprintf ("(inservice=%d) (active_sus_needed=%d) (standby_sus_needed=%d)"
  1081. "\n",
  1082. inservice_count, active_sus_needed, standby_sus_needed);
  1083. /* Determine number of active and standby service units
  1084. * to assign based upon reduction procedure
  1085. */
  1086. if ((inservice_count < active_sus_needed)) {
  1087. dprintf ("assignment VI - partial assignment with SIs drop outs\n");
  1088. su_active_assign = inservice_count;
  1089. su_standby_assign = 0;
  1090. su_spare_assign = 0;
  1091. } else
  1092. if ((inservice_count < active_sus_needed + standby_sus_needed)) {
  1093. dprintf ("assignment V - partial assignment with reduction of"
  1094. " standby units\n");
  1095. su_active_assign = active_sus_needed;
  1096. su_standby_assign = inservice_count - active_sus_needed;
  1097. su_spare_assign = 0;
  1098. } else
  1099. if ((inservice_count < sg->saAmfSGNumPrefActiveSUs + standby_sus_needed)) {
  1100. dprintf ("IV: full assignment with reduction of active service"
  1101. " units\n");
  1102. su_active_assign = inservice_count - standby_sus_needed;
  1103. su_standby_assign = standby_sus_needed;
  1104. su_spare_assign = 0;
  1105. } else
  1106. if ((inservice_count <
  1107. sg->saAmfSGNumPrefActiveSUs + sg->saAmfSGNumPrefStandbySUs)) {
  1108. dprintf ("III: full assignment with reduction of standby service"
  1109. " units\n");
  1110. su_active_assign = sg->saAmfSGNumPrefActiveSUs;
  1111. su_standby_assign = inservice_count - sg->saAmfSGNumPrefActiveSUs;
  1112. su_spare_assign = 0;
  1113. } else
  1114. if ((inservice_count ==
  1115. sg->saAmfSGNumPrefActiveSUs + sg->saAmfSGNumPrefStandbySUs)) {
  1116. if (sg->saAmfSGNumPrefInserviceSUs > inservice_count) {
  1117. dprintf ("II: full assignment with spare reduction\n");
  1118. } else {
  1119. dprintf ("II: full assignment without spares\n");
  1120. }
  1121. su_active_assign = sg->saAmfSGNumPrefActiveSUs;
  1122. su_standby_assign = sg->saAmfSGNumPrefStandbySUs;
  1123. su_spare_assign = 0;
  1124. } else {
  1125. dprintf ("I: full assignment with spares\n");
  1126. su_active_assign = sg->saAmfSGNumPrefActiveSUs;
  1127. su_standby_assign = sg->saAmfSGNumPrefStandbySUs;
  1128. su_spare_assign = inservice_count -
  1129. sg->saAmfSGNumPrefActiveSUs - sg->saAmfSGNumPrefStandbySUs;
  1130. }
  1131. dprintf ("(inservice=%d) (assigning active=%d) (assigning standby=%d)"
  1132. " (assigning spares=%d)\n",
  1133. inservice_count, su_active_assign, su_standby_assign, su_spare_assign);
  1134. if (inservice_count > 0) {
  1135. assigned = sg_assign_nm_active (sg, su_active_assign);
  1136. assigned += sg_assign_nm_standby (sg, su_standby_assign);
  1137. #if 0
  1138. assert (assigned > 0);
  1139. #endif
  1140. sg->saAmfSGNumCurrAssignedSUs = inservice_count;
  1141. /**
  1142. * Phase 2: do the actual assignment to the component
  1143. * TODO: first do active, then standby
  1144. */
  1145. {
  1146. struct amf_si *si;
  1147. struct amf_si_assignment *si_assignment;
  1148. for (si = sg->application->si_head; si != NULL; si = si->next) {
  1149. if (name_match (&si->saAmfSIProtectedbySG, &sg->name)) {
  1150. for (si_assignment = si->assigned_sis;
  1151. si_assignment != NULL;
  1152. si_assignment = si_assignment->next) {
  1153. if (si_assignment->requested_ha_state !=
  1154. si_assignment->saAmfSISUHAState) {
  1155. amf_si_ha_state_assume (
  1156. si_assignment, assign_si_assumed_cbfn);
  1157. }
  1158. }
  1159. }
  1160. }
  1161. }
  1162. }
  1163. LEAVE ("'%s'", sg->name.value);
  1164. return assigned;
  1165. }
  1166. int amf_sg_assign_si_req (struct amf_sg *sg, int dependency_level)
  1167. {
  1168. int posible_to_assign_si;
  1169. sg->avail_state = SG_AC_AssigningOnRequest;
  1170. if ((posible_to_assign_si = assign_si (sg, dependency_level)) == 0) {
  1171. return_to_idle (sg);
  1172. }
  1173. return posible_to_assign_si;
  1174. }
  1175. void amf_sg_failover_node_req (
  1176. struct amf_sg *sg, struct amf_node *node)
  1177. {
  1178. ENTER("'%s, %s'",node->name.value, sg->name.value);
  1179. /*
  1180. * TODO: Defer all new events. Workaround is to exit.
  1181. */
  1182. if (sg->avail_state != SG_AC_Idle) {
  1183. log_printf (LOG_LEVEL_ERROR, "To handle multiple simultaneous SG"
  1184. " recovery actions is not implemented yet:"
  1185. " SG '%s', NODE '%s', avail_state %d",
  1186. sg->name.value, node->name.value, sg->avail_state);
  1187. openais_exit_error (AIS_DONE_FATAL_ERR);
  1188. return;
  1189. }
  1190. set_scope_for_failover_node(sg, node);
  1191. if (has_any_su_in_scope_active_workload (sg)) {
  1192. acsm_enter_deactivating_dependent_workload (sg);
  1193. } else {
  1194. struct amf_su **sus = sg->recovery_scope.sus;
  1195. /* Select next state depending on if some SU in the scope is
  1196. * needs to be terminated.
  1197. */
  1198. while (*sus != NULL) {
  1199. ENTER("SU %s pr_state='%d'",(*sus)->name.value,
  1200. (*sus)->saAmfSUPresenceState);
  1201. if (((*sus)->saAmfSUPresenceState ==
  1202. SA_AMF_PRESENCE_UNINSTANTIATED) ||
  1203. ((*sus)->saAmfSUPresenceState ==
  1204. SA_AMF_PRESENCE_TERMINATION_FAILED) ||
  1205. ((*sus)->saAmfSUPresenceState ==
  1206. SA_AMF_PRESENCE_INSTANTIATION_FAILED)) {
  1207. sus++;
  1208. continue;
  1209. }
  1210. break;
  1211. }
  1212. if (*sus != NULL) {
  1213. acsm_enter_terminating_suspected (sg);
  1214. } else {
  1215. delete_si_assignments_in_scope (sg);
  1216. return_to_idle (sg);
  1217. }
  1218. }
  1219. }
  1220. void amf_sg_start (struct amf_sg *sg, struct amf_node *node)
  1221. {
  1222. struct amf_su *su;
  1223. sg_avail_control_state_t old_avail_state = sg->avail_state;
  1224. int instantiated_sus = 0;
  1225. ENTER ("'%s'", sg->name.value);
  1226. sg->node_to_start = node;
  1227. sg->avail_state = SG_AC_InstantiatingServiceUnits;
  1228. for (su = sg->su_head;
  1229. (su != NULL) && (instantiated_sus < sg->saAmfSGNumPrefInserviceSUs);
  1230. su = su->next) {
  1231. if (node == NULL) {
  1232. /* Cluster start */
  1233. amf_su_instantiate (su);
  1234. instantiated_sus++;
  1235. } else {
  1236. /* Node start, match if SU is hosted on the specified node*/
  1237. if (name_match (&node->name, &su->saAmfSUHostedByNode)) {
  1238. amf_su_instantiate (su);
  1239. instantiated_sus++;
  1240. }
  1241. }
  1242. }
  1243. if (instantiated_sus == 0) {
  1244. sg->avail_state = old_avail_state;
  1245. }
  1246. }
  1247. void amf_sg_su_state_changed (struct amf_sg *sg,
  1248. struct amf_su *su, SaAmfStateT type, int state)
  1249. {
  1250. ENTER ("'%s' SU '%s' state %s",
  1251. sg->name.value, su->name.value, amf_presence_state(state));
  1252. if (type == SA_AMF_PRESENCE_STATE) {
  1253. if (state == SA_AMF_PRESENCE_INSTANTIATED) {
  1254. if (sg->avail_state == SG_AC_InstantiatingServiceUnits) {
  1255. if (no_su_has_presence_state(sg, sg->node_to_start,
  1256. SA_AMF_PRESENCE_INSTANTIATING)) {
  1257. su->sg->avail_state = SG_AC_Idle;
  1258. amf_application_sg_started (
  1259. sg->application, sg, this_amf_node);
  1260. }
  1261. } else if (sg->avail_state == SG_AC_ReparingSu) {
  1262. if (all_su_in_scope_has_presence_state(su->sg,
  1263. SA_AMF_PRESENCE_INSTANTIATED)) {
  1264. su->sg->avail_state = SG_AC_AssigningStandBy;
  1265. if (assign_si (sg, 0) == 0) {
  1266. return_to_idle (sg);
  1267. }
  1268. } else {
  1269. dprintf ("avail-state: %u", sg->avail_state);
  1270. assert (0);
  1271. }
  1272. } else {
  1273. dprintf ("avail-state: %u", sg->avail_state);
  1274. assert (0);
  1275. }
  1276. } else if (state == SA_AMF_PRESENCE_UNINSTANTIATED) {
  1277. if (sg->avail_state == SG_AC_TerminatingSuspected) {
  1278. if (all_su_in_scope_has_presence_state (sg, state)) {
  1279. delete_si_assignments_in_scope (sg);
  1280. if (is_standby_for_non_active_si_in_scope (sg)) {
  1281. acsm_enter_activating_standby (sg);
  1282. } else {
  1283. /*
  1284. * TODO: create SI assignment to spare and assign them
  1285. */
  1286. sg->avail_state = SG_AC_AssigningStandbyToSpare;
  1287. acsm_enter_repairing_su (sg);
  1288. }
  1289. }
  1290. } else {
  1291. assert (0);
  1292. }
  1293. } else if (state == SA_AMF_PRESENCE_INSTANTIATING) {
  1294. ; /* nop */
  1295. } else if (state == SA_AMF_PRESENCE_INSTANTIATION_FAILED) {
  1296. if (sg->avail_state == SG_AC_InstantiatingServiceUnits) {
  1297. if (no_su_has_presence_state(sg, sg->node_to_start,
  1298. SA_AMF_PRESENCE_INSTANTIATING)) {
  1299. su->sg->avail_state = SG_AC_Idle;
  1300. amf_application_sg_started (
  1301. sg->application, sg, this_amf_node);
  1302. }
  1303. }
  1304. } else {
  1305. assert (0);
  1306. }
  1307. } else {
  1308. assert (0);
  1309. }
  1310. }
  1311. void amf_sg_init (void)
  1312. {
  1313. log_init ("AMF");
  1314. }
  1315. void amf_sg_failover_su_req (
  1316. struct amf_sg *sg, struct amf_su *su, struct amf_node *node)
  1317. {
  1318. ENTER ("");
  1319. /*
  1320. * TODO: Defer all new events. Workaround is to exit.
  1321. */
  1322. if (sg->avail_state != SG_AC_Idle) {
  1323. log_printf (LOG_LEVEL_ERROR, "To handle multiple simultaneous SG"
  1324. " recovery actions is not implemented yet:"
  1325. " SG '%s', SU '%s', avail_state %d",
  1326. sg->name.value, su->name.value, sg->avail_state);
  1327. openais_exit_error (AIS_DONE_FATAL_ERR);
  1328. return;
  1329. }
  1330. set_scope_for_failover_su (sg, su);
  1331. if (has_any_su_in_scope_active_workload (sg)) {
  1332. acsm_enter_deactivating_dependent_workload (sg);
  1333. } else {
  1334. acsm_enter_terminating_suspected (sg);
  1335. }
  1336. }
  1337. /**
  1338. * Constructor for SG objects. Adds SG to the list owned by
  1339. * the specified application. Always returns a valid SG
  1340. * object, out-of-memory problems are handled here. Default
  1341. * values are initialized.
  1342. * @param sg
  1343. * @param name
  1344. *
  1345. * @return struct amf_sg*
  1346. */
  1347. struct amf_sg *amf_sg_new (struct amf_application *app, char *name)
  1348. {
  1349. struct amf_sg *sg = amf_calloc (1, sizeof (struct amf_sg));
  1350. setSaNameT (&sg->name, name);
  1351. sg->saAmfSGAdminState = SA_AMF_ADMIN_UNLOCKED;
  1352. sg->saAmfSGNumPrefActiveSUs = 1;
  1353. sg->saAmfSGNumPrefStandbySUs = 1;
  1354. sg->saAmfSGNumPrefInserviceSUs = ~0;
  1355. sg->saAmfSGNumPrefAssignedSUs = ~0;
  1356. sg->saAmfSGCompRestartProb = -1;
  1357. sg->saAmfSGCompRestartMax = ~0;
  1358. sg->saAmfSGSuRestartProb = -1;
  1359. sg->saAmfSGSuRestartMax = ~0;
  1360. sg->saAmfSGAutoAdjustProb = -1;
  1361. sg->saAmfSGAutoRepair = SA_TRUE;
  1362. sg->application = app;
  1363. sg->next = app->sg_head;
  1364. app->sg_head = sg;
  1365. return sg;
  1366. }
  1367. void amf_sg_delete (struct amf_sg *sg)
  1368. {
  1369. struct amf_su *su;
  1370. for (su = sg->su_head; su != NULL;) {
  1371. struct amf_su *tmp = su;
  1372. su = su->next;
  1373. amf_su_delete (tmp);
  1374. }
  1375. free (sg);
  1376. }
  1377. void *amf_sg_serialize (struct amf_sg *sg, int *len)
  1378. {
  1379. char *buf = NULL;
  1380. int offset = 0, size = 0;
  1381. TRACE8 ("%s", sg->name.value);
  1382. buf = amf_serialize_SaNameT (buf, &size, &offset, &sg->name);
  1383. buf = amf_serialize_SaUint32T (buf, &size, &offset, sg->saAmfSGRedundancyModel);
  1384. buf = amf_serialize_SaUint32T (
  1385. buf, &size, &offset, sg->saAmfSGAutoAdjust);
  1386. buf = amf_serialize_SaUint32T (
  1387. buf, &size, &offset, sg->saAmfSGNumPrefActiveSUs);
  1388. buf = amf_serialize_SaUint32T (
  1389. buf, &size, &offset, sg->saAmfSGNumPrefStandbySUs);
  1390. buf = amf_serialize_SaUint32T (
  1391. buf, &size, &offset, sg->saAmfSGNumPrefInserviceSUs);
  1392. buf = amf_serialize_SaUint32T (
  1393. buf, &size, &offset, sg->saAmfSGNumPrefAssignedSUs);
  1394. buf = amf_serialize_SaUint32T (
  1395. buf, &size, &offset, sg->saAmfSGMaxActiveSIsperSUs);
  1396. buf = amf_serialize_SaUint32T (
  1397. buf, &size, &offset, sg->saAmfSGMaxStandbySIsperSUs);
  1398. buf = amf_serialize_SaUint32T (
  1399. buf, &size, &offset, sg->saAmfSGCompRestartProb);
  1400. buf = amf_serialize_SaUint32T (
  1401. buf, &size, &offset, sg->saAmfSGCompRestartMax);
  1402. buf = amf_serialize_SaUint32T (
  1403. buf, &size, &offset, sg->saAmfSGSuRestartProb);
  1404. buf = amf_serialize_SaUint32T (
  1405. buf, &size, &offset, sg->saAmfSGSuRestartMax);
  1406. buf = amf_serialize_SaUint32T (
  1407. buf, &size, &offset, sg->saAmfSGAutoAdjustProb);
  1408. buf = amf_serialize_SaUint32T (
  1409. buf, &size, &offset, sg->saAmfSGAutoRepair);
  1410. buf = amf_serialize_SaUint32T (
  1411. buf, &size, &offset, sg->saAmfSGAdminState);
  1412. buf = amf_serialize_SaUint32T (
  1413. buf, &size, &offset, sg->saAmfSGNumCurrAssignedSUs);
  1414. buf = amf_serialize_SaUint32T (
  1415. buf, &size, &offset, sg->saAmfSGNumCurrNonInstantiatedSpareSUs);
  1416. buf = amf_serialize_SaUint32T (
  1417. buf, &size, &offset, sg->saAmfSGNumCurrInstantiatedSpareSUs);
  1418. buf = amf_serialize_SaStringT (
  1419. buf, &size, &offset, sg->clccli_path);
  1420. buf = amf_serialize_SaUint32T (
  1421. buf, &size, &offset, sg->avail_state);
  1422. *len = offset;
  1423. return buf;
  1424. }
  1425. struct amf_sg *amf_sg_deserialize (struct amf_application *app, char *buf)
  1426. {
  1427. char *tmp = buf;
  1428. struct amf_sg *sg = amf_sg_new (app, "");
  1429. tmp = amf_deserialize_SaNameT (tmp, &sg->name);
  1430. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGRedundancyModel);
  1431. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGAutoAdjust);
  1432. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumPrefActiveSUs);
  1433. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumPrefStandbySUs);
  1434. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumPrefInserviceSUs);
  1435. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumPrefAssignedSUs);
  1436. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGMaxActiveSIsperSUs);
  1437. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGMaxStandbySIsperSUs);
  1438. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGCompRestartProb);
  1439. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGCompRestartMax);
  1440. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGSuRestartProb);
  1441. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGSuRestartMax);
  1442. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGAutoAdjustProb);
  1443. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGAutoRepair);
  1444. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGAdminState);
  1445. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumCurrAssignedSUs);
  1446. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumCurrNonInstantiatedSpareSUs);
  1447. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumCurrInstantiatedSpareSUs);
  1448. tmp = amf_deserialize_SaStringT (tmp, &sg->clccli_path);
  1449. tmp = amf_deserialize_SaUint32T (tmp, &sg->avail_state);
  1450. return sg;
  1451. }
  1452. struct amf_sg *amf_sg_find (struct amf_application *app, char *name)
  1453. {
  1454. struct amf_sg *sg;
  1455. for (sg = app->sg_head; sg != NULL; sg = sg->next) {
  1456. if (sg->name.length == strlen(name) &&
  1457. strncmp (name, (char*)sg->name.value, sg->name.length) == 0) {
  1458. break;
  1459. }
  1460. }
  1461. return sg;
  1462. }