amfsg.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541
  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 standby_su_activated_cbfn (
  151. struct amf_si_assignment *si_assignment, int result);
  152. static void dependent_si_deactivated_cbfn (
  153. struct amf_si_assignment *si_assignment, int result);
  154. static const char *sg_recovery_type_text[] = {
  155. "Unknown",
  156. "FailoverSU",
  157. "FailoverNode"
  158. };
  159. static void return_to_idle (struct amf_sg *sg)
  160. {
  161. SaNameT dn;
  162. ENTER ("sg: %s state: %d", sg->name.value,sg->avail_state);
  163. sg->avail_state = SG_AC_Idle;
  164. if (sg->recovery_scope.recovery_type != 0) {
  165. switch (sg->recovery_scope.recovery_type) {
  166. case SG_RT_FailoverSU:
  167. case SG_RT_FailoverNode:
  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. default:
  176. log_printf (
  177. LOG_NOTICE, "'%s' recovery action finished",
  178. sg_recovery_type_text[0]);
  179. }
  180. }
  181. if (sg->recovery_scope.sus != NULL) {
  182. free ((void *)sg->recovery_scope.sus);
  183. }
  184. if (sg->recovery_scope.sis != NULL) {
  185. free ((void *)sg->recovery_scope.sis);
  186. }
  187. memset (&sg->recovery_scope, 0, sizeof (struct sg_recovery_scope));
  188. }
  189. static int su_instantiated_count (struct amf_sg *sg)
  190. {
  191. int cnt = 0;
  192. struct amf_su *su;
  193. for (su = sg->su_head; su != NULL; su = su->next) {
  194. if (su->saAmfSUPresenceState == SA_AMF_PRESENCE_INSTANTIATED)
  195. cnt++;
  196. }
  197. return cnt;
  198. }
  199. static int has_any_su_in_scope_active_workload (struct amf_sg *sg)
  200. {
  201. struct amf_su **sus= sg->recovery_scope.sus;
  202. struct amf_si_assignment *si_assignment;
  203. while (*sus != NULL) {
  204. si_assignment = amf_su_get_next_si_assignment (*sus, NULL);
  205. while (si_assignment != NULL) {
  206. if (si_assignment->saAmfSISUHAState != SA_AMF_HA_ACTIVE) {
  207. break;
  208. }
  209. si_assignment = amf_su_get_next_si_assignment (
  210. *sus, si_assignment);
  211. }
  212. if (si_assignment != NULL) {
  213. break;
  214. }
  215. sus++;
  216. }
  217. return(*sus == NULL);
  218. }
  219. static int is_standby_for_non_active_si_in_scope (struct amf_sg *sg)
  220. {
  221. struct amf_si **sis= sg->recovery_scope.sis;
  222. struct amf_si_assignment *si_assignment;
  223. /*
  224. * Check if there is any si in the scope which has no active assignment
  225. * and at least one standby assignment.
  226. */
  227. while (*sis != NULL) {
  228. si_assignment = (*sis)->assigned_sis;
  229. while (si_assignment != NULL) {
  230. if (si_assignment->saAmfSISUHAState == SA_AMF_HA_ACTIVE) {
  231. break;
  232. }
  233. si_assignment = si_assignment->next;
  234. }
  235. if (si_assignment == NULL) {
  236. /* There is no ACTIVE assignment ..*/
  237. si_assignment = (*sis)->assigned_sis;
  238. while (si_assignment != NULL) {
  239. if (si_assignment->saAmfSISUHAState == SA_AMF_HA_STANDBY) {
  240. break;
  241. }
  242. si_assignment = si_assignment->next;
  243. }
  244. if (si_assignment != NULL) {
  245. /* .. and one STANDBY assignment*/
  246. break;
  247. }
  248. }
  249. sis++;
  250. }
  251. return(*sis != NULL);
  252. }
  253. static void acsm_enter_terminating_suspected (struct amf_sg *sg)
  254. {
  255. struct amf_su **sus= sg->recovery_scope.sus;
  256. sg->avail_state = SG_AC_TerminatingSuspected;
  257. /*
  258. * Terminate suspected SU(s)
  259. */
  260. while (*sus != 0) {
  261. amf_su_terminate (*sus);
  262. sus++;
  263. }
  264. }
  265. /**
  266. * Callback function used by SI when there is no dependent SI to
  267. * deactivate.
  268. * @param sg
  269. */
  270. static void dependent_si_deactivated_cbfn2 (struct amf_sg *sg)
  271. {
  272. struct amf_su **sus = sg->recovery_scope.sus;
  273. ENTER("'%s'", sg->name.value);
  274. /* Select next state depending on if some SU in the scope is
  275. * needs to be terminated.
  276. */
  277. while (*sus != NULL) {
  278. ENTER("SU %s pr_state='%d'",(*sus)->name.value,
  279. (*sus)->saAmfSUPresenceState);
  280. if (((*sus)->saAmfSUPresenceState ==
  281. SA_AMF_PRESENCE_UNINSTANTIATED) ||
  282. ((*sus)->saAmfSUPresenceState ==
  283. SA_AMF_PRESENCE_TERMINATION_FAILED) ||
  284. ((*sus)->saAmfSUPresenceState ==
  285. SA_AMF_PRESENCE_INSTANTIATION_FAILED)) {
  286. sus++;
  287. continue;
  288. }
  289. break;
  290. }
  291. if (*sus != NULL) {
  292. acsm_enter_terminating_suspected (sg);
  293. } else {
  294. delete_si_assignments_in_scope(sg);
  295. acsm_enter_activating_standby (sg);
  296. }
  297. }
  298. static void timer_function_dependent_si_deactivated2 (void *sg)
  299. {
  300. ENTER ("");
  301. dependent_si_deactivated_cbfn2 (sg);
  302. }
  303. static struct amf_si *si_get_dependent (struct amf_si *si)
  304. {
  305. struct amf_si *tmp_si = NULL;
  306. ENTER("'%p'",si->depends_on);
  307. if (si->depends_on != NULL) {
  308. if (si->depends_on->name.length < SA_MAX_NAME_LENGTH) {
  309. si->depends_on->name.value[si->depends_on->name.length] = '\0';
  310. }
  311. SaNameT res_arr[2];
  312. int is_match;
  313. is_match = sa_amf_grep ((char*)si->depends_on->name.value,
  314. "safDepend=.*,safSi=(.*),safApp=.*",
  315. 2, res_arr);
  316. if (is_match) {
  317. tmp_si = amf_si_find (si->application, (char*)res_arr[1].value);
  318. } else {
  319. log_printf (LOG_LEVEL_ERROR, "distinguished name for "
  320. "amf_si_depedency failed\n");
  321. openais_exit_error (AIS_DONE_FATAL_ERR);
  322. }
  323. }
  324. return tmp_si;
  325. }
  326. struct amf_si *amf_dependent_get_next (struct amf_si *si,
  327. struct amf_si *si_iter)
  328. {
  329. struct amf_si *tmp_si;
  330. struct amf_application *application;
  331. ENTER("");
  332. if (si_iter == NULL) {
  333. assert(amf_cluster != NULL);
  334. application = amf_cluster->application_head;
  335. assert(application != NULL);
  336. tmp_si = application->si_head;
  337. } else {
  338. tmp_si = si_iter->next;
  339. if (tmp_si == NULL) {
  340. application = si->application->next;
  341. if (application == NULL) {
  342. goto out;
  343. }
  344. }
  345. }
  346. for (; tmp_si != NULL; tmp_si = tmp_si->next) {
  347. struct amf_si *depends_on_si = si_get_dependent (tmp_si);
  348. while (depends_on_si != NULL) {
  349. if (depends_on_si == si) {
  350. goto out;
  351. }
  352. depends_on_si = depends_on_si->next;
  353. }
  354. }
  355. out:
  356. return tmp_si;
  357. }
  358. static void acsm_enter_deactivating_dependent_workload (struct amf_sg *sg)
  359. {
  360. struct amf_si **sis= sg->recovery_scope.sis;
  361. struct amf_si_assignment *si_assignment;
  362. int callback_pending = 0;
  363. sg->avail_state = SG_AC_DeactivatingDependantWorkload;
  364. ENTER("'%s'",sg->name.value);
  365. /*
  366. * For each SI in the recovery scope, find all active assignments
  367. * and request them to be deactivated.
  368. */
  369. while (*sis != NULL) {
  370. struct amf_si *dependent_si;
  371. struct amf_si *si = *sis;
  372. si_assignment = si->assigned_sis;
  373. dependent_si = amf_dependent_get_next (si, NULL);
  374. while (dependent_si != NULL) {
  375. si_assignment = dependent_si->assigned_sis;
  376. while (si_assignment != NULL) {
  377. if (si_assignment->saAmfSISUHAState == SA_AMF_HA_ACTIVE) {
  378. si_assignment->requested_ha_state = SA_AMF_HA_QUIESCED;
  379. callback_pending = 1;
  380. amf_si_ha_state_assume (
  381. si_assignment, dependent_si_deactivated_cbfn);
  382. }
  383. si_assignment = si_assignment->next;
  384. }
  385. dependent_si = amf_dependent_get_next (si, dependent_si);
  386. }
  387. sis++;
  388. }
  389. if (callback_pending == 0) {
  390. poll_timer_handle handle;
  391. ENTER("");
  392. poll_timer_add (aisexec_poll_handle, 0, sg,
  393. timer_function_dependent_si_deactivated2, &handle);
  394. }
  395. }
  396. /**
  397. * Enter function for state SG_AC_ActivatingStandby. It activates
  398. * one STANDBY assignment for each SI in the recovery scope.
  399. * @param sg
  400. */
  401. static void acsm_enter_activating_standby (struct amf_sg *sg)
  402. {
  403. struct amf_si **sis= sg->recovery_scope.sis;
  404. struct amf_si_assignment *si_assignment;
  405. ENTER("'%s'",sg->name.value);
  406. sg->avail_state = SG_AC_ActivatingStandby;
  407. /*
  408. * For each SI in the recovery scope, find one standby
  409. * SI assignment and activate it.
  410. */
  411. while (*sis != NULL) {
  412. si_assignment = (*sis)->assigned_sis;
  413. while (si_assignment != NULL) {
  414. if (si_assignment->saAmfSISUHAState == SA_AMF_HA_STANDBY) {
  415. si_assignment->requested_ha_state = SA_AMF_HA_ACTIVE;
  416. amf_si_ha_state_assume (
  417. si_assignment, standby_su_activated_cbfn);
  418. break;
  419. }
  420. si_assignment = si_assignment->next;
  421. }
  422. sis++;
  423. }
  424. }
  425. static void acsm_enter_repairing_su (struct amf_sg *sg)
  426. {
  427. struct amf_su **sus= sg->recovery_scope.sus;
  428. ENTER("'%s'",sg->name.value);
  429. sg->avail_state = SG_AC_ReparingSu;
  430. /*
  431. * Instantiate SUs in current recovery scope until the configured
  432. * preference is fulfiled.
  433. */
  434. while (*sus != NULL) {
  435. if (su_instantiated_count ((*sus)->sg) <
  436. (*sus)->sg->saAmfSGNumPrefInserviceSUs) {
  437. struct amf_node *node = amf_node_find(&((*sus)->saAmfSUHostedByNode));
  438. if (node == NULL) {
  439. log_printf (LOG_LEVEL_ERROR, "no node to hosted on su found"
  440. "amf_si_depedency failed\n");
  441. openais_exit_error (AIS_DONE_FATAL_ERR);
  442. }
  443. if (node->saAmfNodeOperState == SA_AMF_OPERATIONAL_ENABLED) {
  444. amf_su_instantiate ((*sus));
  445. } else {
  446. return_to_idle (sg);
  447. }
  448. }
  449. sus++;
  450. }
  451. }
  452. /**
  453. * Checks if the si pointed out is already in the scope.
  454. * @param sg
  455. * @param si
  456. */
  457. static int is_si_in_scope(struct amf_sg *sg, struct amf_si *si)
  458. {
  459. struct amf_si **tmp_sis= sg->recovery_scope.sis;
  460. while (*tmp_sis != NULL) {
  461. if (*tmp_sis == si) {
  462. break;
  463. }
  464. tmp_sis++;
  465. }
  466. return(*tmp_sis == si);
  467. }
  468. /**
  469. * Adds the si pointed out to the scope.
  470. * @param sg
  471. * @param si
  472. */
  473. static void add_si_to_scope ( struct amf_sg *sg, struct amf_si *si)
  474. {
  475. int number_of_si = 2; /* It shall be at least two */
  476. struct amf_si **tmp_sis= sg->recovery_scope.sis;
  477. ENTER ("'%s'", si->name.value);
  478. while (*tmp_sis != NULL) {
  479. number_of_si++;
  480. tmp_sis++;
  481. }
  482. sg->recovery_scope.sis = (struct amf_si **)
  483. realloc((void *)sg->recovery_scope.sis,
  484. sizeof (struct amf_si *)*number_of_si);
  485. assert (sg->recovery_scope.sis != NULL);
  486. tmp_sis= sg->recovery_scope.sis;
  487. while (*tmp_sis != NULL) {
  488. tmp_sis++;
  489. }
  490. *tmp_sis= si;
  491. }
  492. /**
  493. * Adds the ssu pointed out to the scope.
  494. * @param sg
  495. * @param su
  496. */
  497. static void add_su_to_scope (struct amf_sg *sg, struct amf_su *su)
  498. {
  499. int number_of_su = 2; /* It shall be at least two */
  500. struct amf_su **tmp_sus= sg->recovery_scope.sus;
  501. ENTER ("'%s'", su->name.value);
  502. while (*tmp_sus != NULL) {
  503. number_of_su++;
  504. tmp_sus++;
  505. }
  506. sg->recovery_scope.sus = (struct amf_su **)
  507. realloc((void *)sg->recovery_scope.sus,
  508. sizeof (struct amf_su *)*number_of_su);
  509. assert (sg->recovery_scope.sus != NULL);
  510. tmp_sus= sg->recovery_scope.sus;
  511. while (*tmp_sus != NULL) {
  512. tmp_sus++;
  513. }
  514. *tmp_sus= su;
  515. }
  516. /**
  517. * Set recovery scope for failover SU.
  518. * @param sg
  519. * @param su
  520. */
  521. static void set_scope_for_failover_su (struct amf_sg *sg, struct amf_su *su)
  522. {
  523. struct amf_si_assignment *si_assignment;
  524. struct amf_si **sis;
  525. struct amf_su **sus;
  526. sg->recovery_scope.recovery_type = SG_RT_FailoverSU;
  527. sg->recovery_scope.comp = NULL;
  528. sg->recovery_scope.sus = (struct amf_su **)
  529. calloc (2, sizeof (struct amf_su *));
  530. sg->recovery_scope.sis = (struct amf_si **)
  531. calloc (1, sizeof (struct amf_si *));
  532. assert ((sg->recovery_scope.sus != NULL) &&
  533. (sg->recovery_scope.sis != NULL));
  534. sg->recovery_scope.sus[0] = su;
  535. si_assignment = amf_su_get_next_si_assignment (su, NULL);
  536. while (si_assignment != NULL) {
  537. if (is_si_in_scope(sg, si_assignment->si) == 0) {
  538. add_si_to_scope(sg,si_assignment->si );
  539. }
  540. si_assignment = amf_su_get_next_si_assignment (su, si_assignment);
  541. }
  542. sus= sg->recovery_scope.sus;
  543. dprintf("The following sus are within the scope:\n");
  544. while (*sus != NULL) {
  545. dprintf("%s\n", (*sus)->name.value);
  546. sus++;
  547. }
  548. sis= sg->recovery_scope.sis;
  549. dprintf("The following sis are within the scope:\n");
  550. while (*sis != NULL) {
  551. dprintf("%s\n", (*sis)->name.value);
  552. sis++;
  553. }
  554. }
  555. static void set_scope_for_failover_node (struct amf_sg *sg, struct amf_node *node)
  556. {
  557. struct amf_si_assignment *si_assignment;
  558. struct amf_si **sis;
  559. struct amf_su **sus;
  560. struct amf_su *su;
  561. ENTER ("'%s'", node->name.value);
  562. sg->recovery_scope.recovery_type = SG_RT_FailoverNode;
  563. sg->recovery_scope.comp = NULL;
  564. sg->recovery_scope.sus = (struct amf_su **)
  565. calloc (1, sizeof (struct amf_su *));
  566. sg->recovery_scope.sis = (struct amf_si **)
  567. calloc (1, sizeof (struct amf_si *));
  568. assert ((sg->recovery_scope.sus != NULL) &&
  569. (sg->recovery_scope.sis != NULL));
  570. for (su = sg->su_head; su != NULL; su = su->next) {
  571. if (name_match (&node->name, &su->saAmfSUHostedByNode)) {
  572. add_su_to_scope (sg, su);
  573. }
  574. }
  575. sus = sg->recovery_scope.sus;
  576. while (*sus != 0) {
  577. su = *sus;
  578. si_assignment = amf_su_get_next_si_assignment (su, NULL);
  579. while (si_assignment != NULL) {
  580. if (is_si_in_scope(sg, si_assignment->si) == 0) {
  581. add_si_to_scope(sg, si_assignment->si );
  582. }
  583. si_assignment = amf_su_get_next_si_assignment (su, si_assignment);
  584. }
  585. sus++;
  586. }
  587. sus= sg->recovery_scope.sus;
  588. dprintf("The following sus are within the scope:\n");
  589. while (*sus != NULL) {
  590. dprintf("%s\n", (*sus)->name.value);
  591. sus++;
  592. }
  593. sis = sg->recovery_scope.sis;
  594. dprintf("The following sis are within the scope:\n");
  595. while (*sis != NULL) {
  596. dprintf("%s\n", (*sis)->name.value);
  597. sis++;
  598. }
  599. }
  600. /**
  601. * Delete all SI assignments and all CSI assignments
  602. * by requesting all contained components.
  603. * @param su
  604. */
  605. static void delete_si_assignments (struct amf_su *su)
  606. {
  607. struct amf_csi *csi;
  608. struct amf_si *si;
  609. struct amf_si_assignment *si_assignment;
  610. ENTER ("'%s'", su->name.value);
  611. for (si = su->sg->application->si_head; si != NULL; si = si->next) {
  612. if (!name_match (&si->saAmfSIProtectedbySG, &su->sg->name)) {
  613. continue;
  614. }
  615. for (csi = si->csi_head; csi != NULL; csi = csi->next) {
  616. amf_csi_delete_assignments (csi, su);
  617. }
  618. /*
  619. * TODO: this only works for n+m where each SI list has only two
  620. * assignments, one active and one standby.
  621. * TODO: use DN instead
  622. */
  623. if (si->assigned_sis->su == su) {
  624. si_assignment = si->assigned_sis;
  625. si->assigned_sis = si_assignment->next;
  626. } else {
  627. si_assignment = si->assigned_sis->next;
  628. si->assigned_sis->next = NULL;
  629. }
  630. assert (si_assignment != NULL);
  631. free (si_assignment);
  632. }
  633. }
  634. /**
  635. * Delete all SI assignments and all CSI assignments in current
  636. * recovery scope.
  637. * @param sg
  638. */
  639. static void delete_si_assignments_in_scope (struct amf_sg *sg)
  640. {
  641. struct amf_su **sus= sg->recovery_scope.sus;
  642. while (*sus != NULL) {
  643. delete_si_assignments (*sus);
  644. sus++;
  645. }
  646. }
  647. /**
  648. * Callback function used by SI when an SI has been deactivated.
  649. * @param si_assignment
  650. * @param result
  651. */
  652. static void dependent_si_deactivated_cbfn (
  653. struct amf_si_assignment *si_assignment, int result)
  654. {
  655. struct amf_sg *sg = si_assignment->su->sg;
  656. struct amf_su **sus = sg->recovery_scope.sus;
  657. struct amf_su *su;
  658. ENTER ("'%s', %d", si_assignment->si->name.value, result);
  659. /*
  660. * If all SI assignments for all SUs in the SG are not pending,
  661. * goto next state (TerminatingSuspected).
  662. */
  663. for (su = sg->su_head ; su != NULL; su = su->next) {
  664. struct amf_si_assignment *si_assignment;
  665. si_assignment = amf_su_get_next_si_assignment(su, NULL);
  666. while (si_assignment != NULL) {
  667. if (si_assignment->saAmfSISUHAState !=
  668. si_assignment->requested_ha_state) {
  669. goto still_wating;
  670. }
  671. si_assignment = amf_su_get_next_si_assignment(su, si_assignment);
  672. }
  673. }
  674. still_wating:
  675. if (su == NULL) {
  676. sus = si_assignment->su->sg->recovery_scope.sus;
  677. /* Select next state depending on if some SU in the scope is
  678. * needs to be terminated.
  679. */
  680. while (*sus != NULL) {
  681. if (((*sus)->saAmfSUPresenceState !=
  682. SA_AMF_PRESENCE_UNINSTANTIATED) &&
  683. ((*sus)->saAmfSUPresenceState !=
  684. SA_AMF_PRESENCE_TERMINATION_FAILED) &&
  685. ((*sus)->saAmfSUPresenceState !=
  686. SA_AMF_PRESENCE_INSTANTIATION_FAILED)) {
  687. break;
  688. }
  689. sus++;
  690. }
  691. if (*sus != NULL) {
  692. acsm_enter_terminating_suspected (sg);
  693. } else {
  694. delete_si_assignments_in_scope(sg);
  695. acsm_enter_activating_standby (sg);
  696. }
  697. }
  698. LEAVE("");
  699. }
  700. static void standby_su_activated_cbfn (
  701. struct amf_si_assignment *si_assignment, int result)
  702. {
  703. struct amf_su **sus= si_assignment->su->sg->recovery_scope.sus;
  704. struct amf_si **sis= si_assignment->su->sg->recovery_scope.sis;
  705. ENTER ("'%s', %d", si_assignment->si->name.value, result);
  706. /*
  707. * If all SI assignments for all SIs in the scope are activated, goto next
  708. * state.
  709. */
  710. while (*sis != NULL) {
  711. if ((*sis)->assigned_sis != NULL &&
  712. (*sis)->assigned_sis->saAmfSISUHAState != SA_AMF_HA_ACTIVE) {
  713. break;
  714. }
  715. sis++;
  716. }
  717. if (*sis == NULL) {
  718. /*
  719. * TODO: create SI assignment to spare and assign them
  720. */
  721. (*sus)->sg->avail_state = SG_AC_AssigningStandbyToSpare;
  722. acsm_enter_repairing_su ((*sus)->sg);
  723. }
  724. }
  725. static void assign_si_assumed_cbfn (
  726. struct amf_si_assignment *si_assignment, int result)
  727. {
  728. struct amf_si_assignment *tmp_si_assignment;
  729. struct amf_si *si;
  730. struct amf_sg *sg = si_assignment->su->sg;
  731. int si_assignment_cnt = 0;
  732. int confirmed_assignments = 0;
  733. ENTER ("'%s', %d", si_assignment->si->name.value, result);
  734. /*
  735. * Report to application when all SIs that this SG protects
  736. * has been assigned or go back to idle state if not cluster
  737. * start.
  738. */
  739. for (si = sg->application->si_head; si != NULL; si = si->next) {
  740. if (name_match (&si->saAmfSIProtectedbySG, &sg->name)) {
  741. for (tmp_si_assignment = si->assigned_sis;
  742. tmp_si_assignment != NULL;
  743. tmp_si_assignment = tmp_si_assignment->next) {
  744. si_assignment_cnt++;
  745. if (tmp_si_assignment->requested_ha_state ==
  746. tmp_si_assignment->saAmfSISUHAState) {
  747. confirmed_assignments++;
  748. }
  749. }
  750. }
  751. }
  752. assert (confirmed_assignments != 0);
  753. switch (sg->avail_state) {
  754. case SG_AC_AssigningOnRequest:
  755. if (si_assignment_cnt == confirmed_assignments) {
  756. return_to_idle (sg);
  757. amf_application_sg_assigned (sg->application, sg);
  758. } else {
  759. dprintf ("%d, %d", si_assignment_cnt, confirmed_assignments);
  760. }
  761. break;
  762. case SG_AC_AssigningStandBy:
  763. {
  764. if (si_assignment_cnt == confirmed_assignments) {
  765. return_to_idle (sg);
  766. }
  767. break;
  768. }
  769. default:
  770. dprintf ("%d, %d, %d", sg->avail_state, si_assignment_cnt,
  771. confirmed_assignments);
  772. amf_runtime_attributes_print (amf_cluster);
  773. assert (0);
  774. }
  775. }
  776. static inline int div_round (int a, int b)
  777. {
  778. int res;
  779. assert (b != 0);
  780. res = a / b;
  781. if ((a % b) != 0)
  782. res++;
  783. return res;
  784. }
  785. static int all_su_has_presence_state (
  786. struct amf_sg *sg, SaAmfPresenceStateT state)
  787. {
  788. struct amf_su *su;
  789. int all_set = 1;
  790. for (su = sg->su_head; su != NULL; su = su->next) {
  791. if (su->saAmfSUPresenceState != state) {
  792. all_set = 0;
  793. break;
  794. }
  795. }
  796. return all_set;
  797. }
  798. static int all_su_in_scope_has_presence_state (
  799. struct amf_sg *sg, SaAmfPresenceStateT state)
  800. {
  801. struct amf_su **sus= sg->recovery_scope.sus;
  802. while (*sus != NULL) {
  803. if ((*sus)->saAmfSUPresenceState != state) {
  804. break;
  805. }
  806. sus++;
  807. }
  808. return(*sus == NULL);
  809. }
  810. /**
  811. * Get number of SIs protected by the specified SG.
  812. * @param sg
  813. *
  814. * @return int
  815. */
  816. static int sg_si_count_get (struct amf_sg *sg)
  817. {
  818. struct amf_si *si;
  819. int cnt = 0;
  820. for (si = sg->application->si_head; si != NULL; si = si->next) {
  821. if (name_match (&si->saAmfSIProtectedbySG, &sg->name)) {
  822. cnt += 1;
  823. }
  824. }
  825. return(cnt);
  826. }
  827. static int sg_assign_nm_active (struct amf_sg *sg, int su_active_assign)
  828. {
  829. struct amf_su *su;
  830. struct amf_si *si;
  831. int assigned = 0;
  832. int assign_to_su = 0;
  833. int total_assigned = 0;
  834. int si_left;
  835. int si_total;
  836. int su_left_to_assign = su_active_assign;
  837. si_total = sg_si_count_get (sg);
  838. si_left = si_total;
  839. assign_to_su = div_round (si_left, su_active_assign);
  840. if (assign_to_su > sg->saAmfSGMaxActiveSIsperSUs) {
  841. assign_to_su = sg->saAmfSGMaxActiveSIsperSUs;
  842. }
  843. su = sg->su_head;
  844. while (su != NULL && su_left_to_assign > 0) {
  845. if (amf_su_get_saAmfSUReadinessState (su) !=
  846. SA_AMF_READINESS_IN_SERVICE ||
  847. amf_su_get_saAmfSUNumCurrActiveSIs (su) ==
  848. assign_to_su ||
  849. amf_su_get_saAmfSUNumCurrStandbySIs (su) > 0) {
  850. su = su->next;
  851. continue; /* Not in service */
  852. }
  853. si = sg->application->si_head;
  854. assigned = 0;
  855. assign_to_su = div_round (si_left, su_left_to_assign);
  856. while (si != NULL) {
  857. if (name_match (&si->saAmfSIProtectedbySG, &sg->name) &&
  858. assigned < assign_to_su &&
  859. amf_si_get_saAmfSINumCurrActiveAssignments(si) <
  860. su_active_assign) {
  861. if (amf_si_su_get_saAmfSINumCurrActiveAssignments (si, su) ==
  862. 0) {
  863. assigned += 1;
  864. total_assigned += 1;
  865. amf_su_assign_si (su, si, SA_AMF_HA_ACTIVE);
  866. }
  867. }
  868. si = si->next;
  869. }
  870. su = su->next;
  871. su_left_to_assign -= 1;
  872. si_left -= assigned;
  873. dprintf (" su_left_to_assign =%d, si_left=%d\n",
  874. su_left_to_assign, si_left);
  875. }
  876. assert (total_assigned <= si_total);
  877. if (total_assigned == 0) {
  878. dprintf ("Info: No SIs assigned");
  879. }
  880. LEAVE();
  881. return total_assigned;
  882. }
  883. static int sg_assign_nm_standby (struct amf_sg *sg, int su_standby_assign)
  884. {
  885. struct amf_su *su;
  886. struct amf_si *si;
  887. int assigned = 0;
  888. int assign_to_su = 0;
  889. int total_assigned = 0;
  890. int si_left;
  891. int si_total;
  892. int su_left_to_assign = su_standby_assign;
  893. ENTER ("'%s'", sg->name.value);
  894. if (su_standby_assign == 0) {
  895. return 0;
  896. }
  897. si_total = sg_si_count_get (sg);
  898. si_left = si_total;
  899. assign_to_su = div_round (si_left, su_standby_assign);
  900. if (assign_to_su > sg->saAmfSGMaxStandbySIsperSUs) {
  901. assign_to_su = sg->saAmfSGMaxStandbySIsperSUs;
  902. }
  903. su = sg->su_head;
  904. while (su != NULL && su_left_to_assign > 0) {
  905. if (amf_su_get_saAmfSUReadinessState (su) !=
  906. SA_AMF_READINESS_IN_SERVICE ||
  907. amf_su_get_saAmfSUNumCurrActiveSIs (su) > 0 ||
  908. amf_su_get_saAmfSUNumCurrStandbySIs (su) ==
  909. assign_to_su) {
  910. su = su->next;
  911. continue; /* Not available for assignment */
  912. }
  913. si = sg->application->si_head;
  914. assigned = 0;
  915. assign_to_su = div_round (si_left, su_left_to_assign);
  916. while (si != NULL) {
  917. if (name_match (&si->saAmfSIProtectedbySG, &sg->name) &&
  918. assigned < assign_to_su &&
  919. amf_si_get_saAmfSINumCurrStandbyAssignments (si) <
  920. su_standby_assign) {
  921. if (amf_si_su_get_saAmfSINumCurrStandbyAssignments (si, su) ==
  922. 0) {
  923. assigned += 1;
  924. total_assigned += 1;
  925. amf_su_assign_si (su, si, SA_AMF_HA_STANDBY);
  926. }
  927. }
  928. si = si->next;
  929. }
  930. su_left_to_assign -= 1;
  931. si_left -= assigned;
  932. dprintf (" su_left_to_assign =%d, si_left=%d\n",
  933. su_left_to_assign, si_left);
  934. su = su->next;
  935. }
  936. assert (total_assigned <= si_total);
  937. if (total_assigned == 0) {
  938. dprintf ("Info: No SIs assigned!");
  939. }
  940. return total_assigned;
  941. }
  942. static int su_inservice_count_get (struct amf_sg *sg)
  943. {
  944. struct amf_su *su;
  945. int answer = 0;
  946. for (su = sg->su_head; su != NULL; su = su->next) {
  947. if (amf_su_get_saAmfSUReadinessState (su) ==
  948. SA_AMF_READINESS_IN_SERVICE) {
  949. answer += 1;
  950. }
  951. }
  952. return(answer);
  953. }
  954. /**
  955. * TODO: dependency_level not used, hard coded
  956. * @param sg
  957. * @param dependency_level
  958. */
  959. static void assign_si (struct amf_sg *sg, int dependency_level)
  960. {
  961. int active_sus_needed;
  962. int standby_sus_needed;
  963. int inservice_count;
  964. int su_active_assign;
  965. int su_standby_assign;
  966. int su_spare_assign;
  967. int assigned = 0;
  968. ENTER ("'%s'", sg->name.value);
  969. /**
  970. * Phase 1: Calculate assignments and create all runtime objects in
  971. * information model. Do not do the actual assignment, done in
  972. * phase 2.
  973. */
  974. /**
  975. * Calculate number of SUs to assign to active or standby state
  976. */
  977. inservice_count = (float)su_inservice_count_get (sg);
  978. active_sus_needed = div_round (
  979. sg_si_count_get (sg) * sg->saAmfSGNumPrefActiveSUs,
  980. sg->saAmfSGMaxActiveSIsperSUs);
  981. standby_sus_needed = div_round (
  982. sg_si_count_get (sg) * sg->saAmfSGNumPrefStandbySUs,
  983. sg->saAmfSGMaxStandbySIsperSUs);
  984. dprintf ("(inservice=%d) (active_sus_needed=%d) (standby_sus_needed=%d)"
  985. "\n",
  986. inservice_count, active_sus_needed, standby_sus_needed);
  987. /* Determine number of active and standby service units
  988. * to assign based upon reduction procedure
  989. */
  990. if ((inservice_count < active_sus_needed)) {
  991. dprintf ("assignment VI - partial assignment with SIs drop outs\n");
  992. su_active_assign = inservice_count;
  993. su_standby_assign = 0;
  994. su_spare_assign = 0;
  995. } else
  996. if ((inservice_count < active_sus_needed + standby_sus_needed)) {
  997. dprintf ("assignment V - partial assignment with reduction of"
  998. " standby units\n");
  999. su_active_assign = active_sus_needed;
  1000. su_standby_assign = inservice_count - active_sus_needed;
  1001. su_spare_assign = 0;
  1002. } else
  1003. if ((inservice_count < sg->saAmfSGNumPrefActiveSUs + standby_sus_needed)) {
  1004. dprintf ("IV: full assignment with reduction of active service"
  1005. " units\n");
  1006. su_active_assign = inservice_count - standby_sus_needed;
  1007. su_standby_assign = standby_sus_needed;
  1008. su_spare_assign = 0;
  1009. } else
  1010. if ((inservice_count <
  1011. sg->saAmfSGNumPrefActiveSUs + sg->saAmfSGNumPrefStandbySUs)) {
  1012. dprintf ("III: full assignment with reduction of standby service"
  1013. " units\n");
  1014. su_active_assign = sg->saAmfSGNumPrefActiveSUs;
  1015. su_standby_assign = inservice_count - sg->saAmfSGNumPrefActiveSUs;
  1016. su_spare_assign = 0;
  1017. } else
  1018. if ((inservice_count ==
  1019. sg->saAmfSGNumPrefActiveSUs + sg->saAmfSGNumPrefStandbySUs)) {
  1020. if (sg->saAmfSGNumPrefInserviceSUs > inservice_count) {
  1021. dprintf ("II: full assignment with spare reduction\n");
  1022. } else {
  1023. dprintf ("II: full assignment without spares\n");
  1024. }
  1025. su_active_assign = sg->saAmfSGNumPrefActiveSUs;
  1026. su_standby_assign = sg->saAmfSGNumPrefStandbySUs;
  1027. su_spare_assign = 0;
  1028. } else {
  1029. dprintf ("I: full assignment with spares\n");
  1030. su_active_assign = sg->saAmfSGNumPrefActiveSUs;
  1031. su_standby_assign = sg->saAmfSGNumPrefStandbySUs;
  1032. su_spare_assign = inservice_count -
  1033. sg->saAmfSGNumPrefActiveSUs - sg->saAmfSGNumPrefStandbySUs;
  1034. }
  1035. dprintf ("(inservice=%d) (assigning active=%d) (assigning standby=%d)"
  1036. " (assigning spares=%d)\n",
  1037. inservice_count, su_active_assign, su_standby_assign, su_spare_assign);
  1038. assigned = sg_assign_nm_active (sg, su_active_assign);
  1039. assigned += sg_assign_nm_standby (sg, su_standby_assign);
  1040. assert (assigned > 0);
  1041. sg->saAmfSGNumCurrAssignedSUs = inservice_count;
  1042. /**
  1043. * Phase 2: do the actual assignment to the component
  1044. * TODO: first do active, then standby
  1045. */
  1046. {
  1047. struct amf_si *si;
  1048. struct amf_si_assignment *si_assignment;
  1049. for (si = sg->application->si_head; si != NULL; si = si->next) {
  1050. if (name_match (&si->saAmfSIProtectedbySG, &sg->name)) {
  1051. for (si_assignment = si->assigned_sis; si_assignment != NULL;
  1052. si_assignment = si_assignment->next) {
  1053. if (si_assignment->requested_ha_state !=
  1054. si_assignment->saAmfSISUHAState) {
  1055. amf_si_ha_state_assume (
  1056. si_assignment, assign_si_assumed_cbfn);
  1057. }
  1058. }
  1059. }
  1060. }
  1061. }
  1062. LEAVE ("'%s'", sg->name.value);
  1063. }
  1064. void amf_sg_assign_si (struct amf_sg *sg, int dependency_level)
  1065. {
  1066. sg->avail_state = SG_AC_AssigningOnRequest;
  1067. assign_si (sg, dependency_level);
  1068. }
  1069. void amf_sg_failover_node_req (
  1070. struct amf_sg *sg, struct amf_node *node)
  1071. {
  1072. ENTER("'%s'",node->name.value);
  1073. /*
  1074. * TODO: Defer all new events. Workaround is to exit.
  1075. */
  1076. if (sg->avail_state != SG_AC_Idle) {
  1077. log_printf (LOG_LEVEL_ERROR, "To handle multiple simultaneous SG"
  1078. " recovery actions is not implemented yet:"
  1079. " SG '%s', NODE '%s', avail_state %d",
  1080. sg->name.value, node->name.value, sg->avail_state);
  1081. openais_exit_error (AIS_DONE_FATAL_ERR);
  1082. return;
  1083. }
  1084. set_scope_for_failover_node(sg, node);
  1085. if (has_any_su_in_scope_active_workload (sg)) {
  1086. acsm_enter_deactivating_dependent_workload (sg);
  1087. } else {
  1088. struct amf_su **sus = sg->recovery_scope.sus;
  1089. /* Select next state depending on if some SU in the scope is
  1090. * needs to be terminated.
  1091. */
  1092. while (*sus != NULL) {
  1093. ENTER("SU %s pr_state='%d'",(*sus)->name.value,
  1094. (*sus)->saAmfSUPresenceState);
  1095. if (((*sus)->saAmfSUPresenceState ==
  1096. SA_AMF_PRESENCE_UNINSTANTIATED) ||
  1097. ((*sus)->saAmfSUPresenceState ==
  1098. SA_AMF_PRESENCE_TERMINATION_FAILED) ||
  1099. ((*sus)->saAmfSUPresenceState ==
  1100. SA_AMF_PRESENCE_INSTANTIATION_FAILED)) {
  1101. sus++;
  1102. continue;
  1103. }
  1104. break;
  1105. }
  1106. if (*sus != NULL) {
  1107. acsm_enter_terminating_suspected (sg);
  1108. } else {
  1109. delete_si_assignments_in_scope (sg);
  1110. return_to_idle (sg);
  1111. }
  1112. }
  1113. }
  1114. void amf_sg_start (struct amf_sg *sg, struct amf_node *node)
  1115. {
  1116. struct amf_su *su;
  1117. sg_avail_control_state_t old_avail_state = sg->avail_state;
  1118. int instantiated_sus = 0;
  1119. ENTER ("'%s'", sg->name.value);
  1120. sg->avail_state = SG_AC_InstantiatingServiceUnits;
  1121. for (su = sg->su_head; su != NULL; su = su->next) {
  1122. if (node == NULL) {
  1123. /* Cluster start */
  1124. amf_su_instantiate (su);
  1125. instantiated_sus++;
  1126. } else {
  1127. /* Node start, match if SU is hosted on the specified node */
  1128. if (name_match (&node->name, &su->saAmfSUHostedByNode)) {
  1129. amf_su_instantiate (su);
  1130. instantiated_sus++;
  1131. }
  1132. }
  1133. }
  1134. if (instantiated_sus == 0) {
  1135. sg->avail_state = old_avail_state;
  1136. }
  1137. }
  1138. void amf_sg_su_state_changed (struct amf_sg *sg,
  1139. struct amf_su *su, SaAmfStateT type, int state)
  1140. {
  1141. ENTER ("'%s' SU '%s' state %s",
  1142. sg->name.value, su->name.value, amf_presence_state(state));
  1143. if (type == SA_AMF_PRESENCE_STATE) {
  1144. if (state == SA_AMF_PRESENCE_INSTANTIATED) {
  1145. if (sg->avail_state == SG_AC_InstantiatingServiceUnits) {
  1146. if (all_su_has_presence_state(su->sg,
  1147. SA_AMF_PRESENCE_INSTANTIATED)) {
  1148. su->sg->avail_state = SG_AC_Idle;
  1149. amf_application_sg_started (
  1150. sg->application, sg, this_amf_node);
  1151. }
  1152. } else if (sg->avail_state == SG_AC_ReparingSu) {
  1153. if (all_su_in_scope_has_presence_state(su->sg,
  1154. SA_AMF_PRESENCE_INSTANTIATED)) {
  1155. su->sg->avail_state = SG_AC_AssigningStandBy;
  1156. assign_si (sg, 0);
  1157. } else {
  1158. dprintf ("avail-state: %u", sg->avail_state);
  1159. assert (0);
  1160. }
  1161. } else {
  1162. assert (0);
  1163. }
  1164. } else if (state == SA_AMF_PRESENCE_UNINSTANTIATED) {
  1165. if (sg->avail_state == SG_AC_TerminatingSuspected) {
  1166. if (all_su_in_scope_has_presence_state (sg, state)) {
  1167. delete_si_assignments_in_scope (sg);
  1168. if (is_standby_for_non_active_si_in_scope (sg)) {
  1169. acsm_enter_activating_standby (sg);
  1170. } else {
  1171. /*
  1172. * TODO: create SI assignment to spare and assign them
  1173. */
  1174. sg->avail_state = SG_AC_AssigningStandbyToSpare;
  1175. acsm_enter_repairing_su (sg);
  1176. }
  1177. }
  1178. } else {
  1179. assert (0);
  1180. }
  1181. } else {
  1182. assert (0);
  1183. }
  1184. } else {
  1185. assert (0);
  1186. }
  1187. }
  1188. void amf_sg_init (void)
  1189. {
  1190. log_init ("AMF");
  1191. }
  1192. void amf_sg_failover_su_req (
  1193. struct amf_sg *sg, struct amf_su *su, struct amf_node *node)
  1194. {
  1195. ENTER ("");
  1196. /*
  1197. * TODO: Defer all new events. Workaround is to exit.
  1198. */
  1199. if (sg->avail_state != SG_AC_Idle) {
  1200. log_printf (LOG_LEVEL_ERROR, "To handle multiple simultaneous SG"
  1201. " recovery actions is not implemented yet:"
  1202. " SG '%s', SU '%s', avail_state %d",
  1203. sg->name.value, su->name.value, sg->avail_state);
  1204. openais_exit_error (AIS_DONE_FATAL_ERR);
  1205. return;
  1206. }
  1207. set_scope_for_failover_su (sg, su);
  1208. if (has_any_su_in_scope_active_workload (sg)) {
  1209. acsm_enter_deactivating_dependent_workload (sg);
  1210. } else {
  1211. acsm_enter_terminating_suspected (sg);
  1212. }
  1213. }
  1214. /**
  1215. * Constructor for SG objects. Adds SG to the list owned by
  1216. * the specified application. Always returns a valid SG
  1217. * object, out-of-memory problems are handled here. Default
  1218. * values are initialized.
  1219. * @param sg
  1220. * @param name
  1221. *
  1222. * @return struct amf_sg*
  1223. */
  1224. struct amf_sg *amf_sg_new (struct amf_application *app, char *name)
  1225. {
  1226. struct amf_sg *sg = calloc (1, sizeof (struct amf_sg));
  1227. if (sg == NULL) {
  1228. openais_exit_error (AIS_DONE_OUT_OF_MEMORY);
  1229. }
  1230. sg->next = app->sg_head;
  1231. app->sg_head = sg;
  1232. sg->saAmfSGAdminState = SA_AMF_ADMIN_UNLOCKED;
  1233. sg->saAmfSGNumPrefActiveSUs = 1;
  1234. sg->saAmfSGNumPrefStandbySUs = 1;
  1235. sg->saAmfSGNumPrefInserviceSUs = ~0;
  1236. sg->saAmfSGCompRestartProb = -1;
  1237. sg->saAmfSGCompRestartMax = ~0;
  1238. sg->saAmfSGSuRestartProb = -1;
  1239. sg->saAmfSGSuRestartMax = ~0;
  1240. sg->saAmfSGAutoAdjustProb = -1;
  1241. sg->saAmfSGAutoRepair = SA_TRUE;
  1242. sg->application = app;
  1243. setSaNameT (&sg->name, name);
  1244. return sg;
  1245. }
  1246. void amf_sg_delete (struct amf_sg *sg)
  1247. {
  1248. struct amf_su *su;
  1249. for (su = sg->su_head; su != NULL;) {
  1250. struct amf_su *tmp = su;
  1251. su = su->next;
  1252. amf_su_delete (tmp);
  1253. }
  1254. free (sg);
  1255. }
  1256. void *amf_sg_serialize (struct amf_sg *sg, int *len)
  1257. {
  1258. char *buf = NULL;
  1259. int offset = 0, size = 0;
  1260. TRACE8 ("%s", sg->name.value);
  1261. buf = amf_serialize_SaNameT (buf, &size, &offset, &sg->name);
  1262. buf = amf_serialize_SaUint32T (buf, &size, &offset, sg->saAmfSGRedundancyModel);
  1263. buf = amf_serialize_SaUint32T (
  1264. buf, &size, &offset, sg->saAmfSGAutoAdjust);
  1265. buf = amf_serialize_SaUint32T (
  1266. buf, &size, &offset, sg->saAmfSGNumPrefActiveSUs);
  1267. buf = amf_serialize_SaUint32T (
  1268. buf, &size, &offset, sg->saAmfSGNumPrefStandbySUs);
  1269. buf = amf_serialize_SaUint32T (
  1270. buf, &size, &offset, sg->saAmfSGNumPrefInserviceSUs);
  1271. buf = amf_serialize_SaUint32T (
  1272. buf, &size, &offset, sg->saAmfSGNumPrefAssignedSUs);
  1273. buf = amf_serialize_SaUint32T (
  1274. buf, &size, &offset, sg->saAmfSGMaxActiveSIsperSUs);
  1275. buf = amf_serialize_SaUint32T (
  1276. buf, &size, &offset, sg->saAmfSGMaxStandbySIsperSUs);
  1277. buf = amf_serialize_SaUint32T (
  1278. buf, &size, &offset, sg->saAmfSGCompRestartProb);
  1279. buf = amf_serialize_SaUint32T (
  1280. buf, &size, &offset, sg->saAmfSGCompRestartMax);
  1281. buf = amf_serialize_SaUint32T (
  1282. buf, &size, &offset, sg->saAmfSGSuRestartProb);
  1283. buf = amf_serialize_SaUint32T (
  1284. buf, &size, &offset, sg->saAmfSGSuRestartMax);
  1285. buf = amf_serialize_SaUint32T (
  1286. buf, &size, &offset, sg->saAmfSGAutoAdjustProb);
  1287. buf = amf_serialize_SaUint32T (
  1288. buf, &size, &offset, sg->saAmfSGAutoRepair);
  1289. buf = amf_serialize_SaUint32T (
  1290. buf, &size, &offset, sg->saAmfSGAdminState);
  1291. buf = amf_serialize_SaUint32T (
  1292. buf, &size, &offset, sg->saAmfSGNumCurrAssignedSUs);
  1293. buf = amf_serialize_SaUint32T (
  1294. buf, &size, &offset, sg->saAmfSGNumCurrNonInstantiatedSpareSUs);
  1295. buf = amf_serialize_SaUint32T (
  1296. buf, &size, &offset, sg->saAmfSGNumCurrInstantiatedSpareSUs);
  1297. buf = amf_serialize_SaStringT (
  1298. buf, &size, &offset, sg->clccli_path);
  1299. buf = amf_serialize_SaUint32T (
  1300. buf, &size, &offset, sg->avail_state);
  1301. *len = offset;
  1302. return buf;
  1303. }
  1304. struct amf_sg *amf_sg_deserialize (
  1305. struct amf_application *app, char *buf, int size)
  1306. {
  1307. char *tmp = buf;
  1308. struct amf_sg *sg;
  1309. sg = amf_sg_new (app, "");
  1310. tmp = amf_deserialize_SaNameT (tmp, &sg->name);
  1311. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGRedundancyModel);
  1312. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGAutoAdjust);
  1313. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumPrefActiveSUs);
  1314. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumPrefStandbySUs);
  1315. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumPrefInserviceSUs);
  1316. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumPrefAssignedSUs);
  1317. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGMaxActiveSIsperSUs);
  1318. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGMaxStandbySIsperSUs);
  1319. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGCompRestartProb);
  1320. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGCompRestartMax);
  1321. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGSuRestartProb);
  1322. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGSuRestartMax);
  1323. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGAutoAdjustProb);
  1324. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGAutoRepair);
  1325. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGAdminState);
  1326. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumCurrAssignedSUs);
  1327. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumCurrNonInstantiatedSpareSUs);
  1328. tmp = amf_deserialize_SaUint32T (tmp, &sg->saAmfSGNumCurrInstantiatedSpareSUs);
  1329. tmp = amf_deserialize_SaStringT (tmp, &sg->clccli_path);
  1330. tmp = amf_deserialize_SaUint32T (tmp, &sg->avail_state);
  1331. return sg;
  1332. }
  1333. struct amf_sg *amf_sg_find (struct amf_application *app, char *name)
  1334. {
  1335. struct amf_sg *sg;
  1336. assert (app != NULL && name != NULL);
  1337. for (sg = app->sg_head; sg != NULL; sg = sg->next) {
  1338. if (strncmp (name, (char*)sg->name.value, sg->name.length) == 0) {
  1339. break;
  1340. }
  1341. }
  1342. return sg;
  1343. }