pacemaker  2.1.8-3980678f03
Scalable High-Availability cluster resource manager
native_find_rsc_test.c
Go to the documentation of this file.
1 /*
2  * Copyright 2022-2024 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU General Public License version 2
7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
13 #include <crm/common/scheduler.h>
14 #include <crm/common/xml.h>
15 #include <crm/pengine/internal.h>
16 #include <crm/pengine/status.h>
17 
18 xmlNode *input = NULL;
20 
25 
26 static int
27 setup(void **state) {
28  char *path = NULL;
29 
30  crm_xml_init();
31 
32  path = crm_strdup_printf("%s/crm_mon.xml", getenv("PCMK_CTS_CLI_DIR"));
34  free(path);
35 
36  if (input == NULL) {
37  return 1;
38  }
39 
41 
42  if (scheduler == NULL) {
43  return 1;
44  }
45 
49 
51 
52  /* Get references to the cluster nodes so we don't have to find them repeatedly. */
53  cluster01 = pcmk_find_node(scheduler, "cluster01");
54  cluster02 = pcmk_find_node(scheduler, "cluster02");
55  httpd_bundle_0 = pcmk_find_node(scheduler, "httpd-bundle-0");
56 
57  /* Get references to several resources we use frequently. */
58  for (GList *iter = scheduler->resources; iter != NULL; iter = iter->next) {
59  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
60 
61  if (strcmp(rsc->id, "exim-group") == 0) {
62  exim_group = rsc;
63  } else if (strcmp(rsc->id, "httpd-bundle") == 0) {
64  httpd_bundle = rsc;
65  } else if (strcmp(rsc->id, "inactive-clone") == 0) {
66  inactive_clone = rsc;
67  } else if (strcmp(rsc->id, "inactive-group") == 0) {
68  inactive_group = rsc;
69  } else if (strcmp(rsc->id, "mysql-clone-group") == 0) {
70  mysql_clone_group = rsc;
71  } else if (strcmp(rsc->id, "promotable-clone") == 0) {
72  promotable_clone = rsc;
73  }
74  }
75 
76  return 0;
77 }
78 
79 static int
80 teardown(void **state) {
82 
83  return 0;
84 }
85 
86 static void
87 bad_args(void **state) {
88  pcmk_resource_t *rsc = g_list_first(scheduler->resources)->data;
89  char *id = rsc->id;
90  char *name = NULL;
91 
92  assert_non_null(rsc);
93 
94  assert_null(native_find_rsc(NULL, "dummy", NULL, 0));
95  assert_null(native_find_rsc(rsc, NULL, NULL, 0));
96 
97  /* No resources exist with these names. */
98  name = crm_strdup_printf("%sX", rsc->id);
99  assert_null(native_find_rsc(rsc, name, NULL, 0));
100  free(name);
101 
102  name = crm_strdup_printf("x%s", rsc->id);
103  assert_null(native_find_rsc(rsc, name, NULL, 0));
104  free(name);
105 
106  name = g_ascii_strup(rsc->id, -1);
107  assert_null(native_find_rsc(rsc, name, NULL, 0));
108  g_free(name);
109 
110  /* Fails because resource ID is NULL. */
111  rsc->id = NULL;
112  assert_null(native_find_rsc(rsc, id, NULL, 0));
113  rsc->id = id;
114 }
115 
116 static void
117 primitive_rsc(void **state) {
118  pcmk_resource_t *dummy = NULL;
119 
120  /* Find the "dummy" resource, which is the only one with that ID in the set. */
121  for (GList *iter = scheduler->resources; iter != NULL; iter = iter->next) {
122  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
123 
124  if (strcmp(rsc->id, "dummy") == 0) {
125  dummy = rsc;
126  break;
127  }
128  }
129 
130  assert_non_null(dummy);
131 
132  /* Passes because NULL was passed for node, regardless of flags. */
133  assert_ptr_equal(dummy, native_find_rsc(dummy, "dummy", NULL, 0));
134  assert_ptr_equal(dummy,
135  native_find_rsc(dummy, "dummy", NULL,
137 
138  /* Fails because resource is not a clone (nor cloned). */
139  assert_null(native_find_rsc(dummy, "dummy", NULL,
141  assert_null(native_find_rsc(dummy, "dummy", cluster02,
143 
144  /* Fails because dummy is not running on cluster01, even with the right flags. */
145  assert_null(native_find_rsc(dummy, "dummy", cluster01,
147 
148  // Fails because pcmk_rsc_match_current_node is required if a node is given
149  assert_null(native_find_rsc(dummy, "dummy", cluster02, 0));
150 
151  /* Passes because dummy is running on cluster02. */
152  assert_ptr_equal(dummy,
153  native_find_rsc(dummy, "dummy", cluster02,
155 }
156 
157 static void
158 group_rsc(void **state) {
159  assert_non_null(exim_group);
160 
161  /* Passes because NULL was passed for node, regardless of flags. */
162  assert_ptr_equal(exim_group, native_find_rsc(exim_group, "exim-group", NULL, 0));
163  assert_ptr_equal(exim_group,
164  native_find_rsc(exim_group, "exim-group", NULL,
166 
167  /* Fails because resource is not a clone (nor cloned). */
168  assert_null(native_find_rsc(exim_group, "exim-group", NULL,
170  assert_null(native_find_rsc(exim_group, "exim-group", cluster01,
172 
173  /* Fails because none of exim-group's children are running on cluster01, even with the right flags. */
174  assert_null(native_find_rsc(exim_group, "exim-group", cluster01,
176 
177  // Fails because pcmk_rsc_match_current_node is required if a node is given
178  assert_null(native_find_rsc(exim_group, "exim-group", cluster01, 0));
179 
180  /* Passes because one of exim-group's children is running on cluster02. */
181  assert_ptr_equal(exim_group,
182  native_find_rsc(exim_group, "exim-group", cluster02,
184 }
185 
186 static void
187 inactive_group_rsc(void **state) {
188  assert_non_null(inactive_group);
189 
190  /* Passes because NULL was passed for node, regardless of flags. */
191  assert_ptr_equal(inactive_group, native_find_rsc(inactive_group, "inactive-group", NULL, 0));
192  assert_ptr_equal(inactive_group,
193  native_find_rsc(inactive_group, "inactive-group", NULL,
195 
196  /* Fails because resource is not a clone (nor cloned). */
197  assert_null(native_find_rsc(inactive_group, "inactive-group", NULL,
199  assert_null(native_find_rsc(inactive_group, "inactive-group", cluster01,
201 
202  /* Fails because none of inactive-group's children are running. */
203  assert_null(native_find_rsc(inactive_group, "inactive-group", cluster01,
205  assert_null(native_find_rsc(inactive_group, "inactive-group", cluster02,
207 }
208 
209 static void
210 group_member_rsc(void **state) {
211  pcmk_resource_t *public_ip = NULL;
212 
213  /* Find the "Public-IP" resource, a member of "exim-group". */
214  for (GList *iter = exim_group->children; iter != NULL; iter = iter->next) {
215  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
216 
217  if (strcmp(rsc->id, "Public-IP") == 0) {
218  public_ip = rsc;
219  break;
220  }
221  }
222 
223  assert_non_null(public_ip);
224 
225  /* Passes because NULL was passed for node, regardless of flags. */
226  assert_ptr_equal(public_ip, native_find_rsc(public_ip, "Public-IP", NULL, 0));
227  assert_ptr_equal(public_ip,
228  native_find_rsc(public_ip, "Public-IP", NULL,
230 
231  /* Fails because resource is not a clone (nor cloned). */
232  assert_null(native_find_rsc(public_ip, "Public-IP", NULL,
234  assert_null(native_find_rsc(public_ip, "Public-IP", cluster02,
236 
237  /* Fails because Public-IP is not running on cluster01, even with the right flags. */
238  assert_null(native_find_rsc(public_ip, "Public-IP", cluster01,
240 
241  // Fails because pcmk_rsc_match_current_node is required if a node is given
242  assert_null(native_find_rsc(public_ip, "Public-IP", cluster02, 0));
243 
244  /* Passes because Public-IP is running on cluster02. */
245  assert_ptr_equal(public_ip,
246  native_find_rsc(public_ip, "Public-IP", cluster02,
248 }
249 
250 static void
251 inactive_group_member_rsc(void **state) {
252  pcmk_resource_t *inactive_dummy_1 = NULL;
253 
254  /* Find the "inactive-dummy-1" resource, a member of "inactive-group". */
255  for (GList *iter = inactive_group->children; iter != NULL; iter = iter->next) {
256  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
257 
258  if (strcmp(rsc->id, "inactive-dummy-1") == 0) {
259  inactive_dummy_1 = rsc;
260  break;
261  }
262  }
263 
264  assert_non_null(inactive_dummy_1);
265 
266  /* Passes because NULL was passed for node, regardless of flags. */
267  assert_ptr_equal(inactive_dummy_1, native_find_rsc(inactive_dummy_1, "inactive-dummy-1", NULL, 0));
268  assert_ptr_equal(inactive_dummy_1,
269  native_find_rsc(inactive_dummy_1, "inactive-dummy-1", NULL,
271 
272  /* Fails because resource is not a clone (nor cloned). */
273  assert_null(native_find_rsc(inactive_dummy_1, "inactive-dummy-1", NULL,
275  assert_null(native_find_rsc(inactive_dummy_1, "inactive-dummy-1", cluster01,
277 
278  /* Fails because inactive-dummy-1 is not running. */
279  assert_null(native_find_rsc(inactive_dummy_1, "inactive-dummy-1", cluster01,
281  assert_null(native_find_rsc(inactive_dummy_1, "inactive-dummy-1", cluster02,
283 }
284 
285 static void
286 clone_rsc(void **state) {
287  assert_non_null(promotable_clone);
288 
289  /* Passes because NULL was passed for node, regardless of flags. */
290  assert_ptr_equal(promotable_clone, native_find_rsc(promotable_clone, "promotable-clone", NULL, 0));
291  assert_ptr_equal(promotable_clone,
292  native_find_rsc(promotable_clone, "promotable-clone", NULL,
294  assert_ptr_equal(promotable_clone,
295  native_find_rsc(promotable_clone, "promotable-clone", NULL,
297 
298  // Fails because pcmk_rsc_match_current_node is required if a node is given
299  assert_null(native_find_rsc(promotable_clone, "promotable-clone", cluster01, 0));
300 
301  /* Passes because one of ping-clone's children is running on cluster01. */
302  assert_ptr_equal(promotable_clone,
303  native_find_rsc(promotable_clone, "promotable-clone",
305 
306  // Fails because pcmk_rsc_match_current_node is required if a node is given
307  assert_null(native_find_rsc(promotable_clone, "promotable-clone", cluster02, 0));
308 
309  /* Passes because one of ping_clone's children is running on cluster02. */
310  assert_ptr_equal(promotable_clone,
311  native_find_rsc(promotable_clone, "promotable-clone",
313 
314  // Passes for previous reasons, plus includes pcmk_rsc_match_clone_only
315  assert_ptr_equal(promotable_clone,
316  native_find_rsc(promotable_clone, "promotable-clone",
317  cluster01,
320  assert_ptr_equal(promotable_clone,
321  native_find_rsc(promotable_clone, "promotable-clone",
322  cluster02,
325 }
326 
327 static void
328 inactive_clone_rsc(void **state) {
329  assert_non_null(inactive_clone);
330 
331  /* Passes because NULL was passed for node, regardless of flags. */
332  assert_ptr_equal(inactive_clone, native_find_rsc(inactive_clone, "inactive-clone", NULL, 0));
333  assert_ptr_equal(inactive_clone,
334  native_find_rsc(inactive_clone, "inactive-clone", NULL,
336  assert_ptr_equal(inactive_clone,
337  native_find_rsc(inactive_clone, "inactive-clone", NULL,
339 
340  /* Fails because none of inactive-clone's children are running. */
341  assert_null(native_find_rsc(inactive_clone, "inactive-clone", cluster01,
344  assert_null(native_find_rsc(inactive_clone, "inactive-clone", cluster02,
347 }
348 
349 static void
350 clone_instance_rsc(void **state) {
353 
354  /* Find the "promotable-rsc:0" and "promotable-rsc:1" resources, members of "promotable-clone". */
355  for (GList *iter = promotable_clone->children; iter != NULL; iter = iter->next) {
356  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
357 
358  if (strcmp(rsc->id, "promotable-rsc:0") == 0) {
359  promotable_0 = rsc;
360  } else if (strcmp(rsc->id, "promotable-rsc:1") == 0) {
361  promotable_1 = rsc;
362  }
363  }
364 
365  assert_non_null(promotable_0);
366  assert_non_null(promotable_1);
367 
368  /* Passes because NULL was passed for node, regardless of flags. */
369  assert_ptr_equal(promotable_0, native_find_rsc(promotable_0, "promotable-rsc:0", NULL, 0));
370  assert_ptr_equal(promotable_0,
371  native_find_rsc(promotable_0, "promotable-rsc:0", NULL,
373  assert_ptr_equal(promotable_1, native_find_rsc(promotable_1, "promotable-rsc:1", NULL, 0));
374  assert_ptr_equal(promotable_1,
375  native_find_rsc(promotable_1, "promotable-rsc:1", NULL,
377 
378  // Fails because pcmk_rsc_match_current_node is required if a node is given
379  assert_null(native_find_rsc(promotable_0, "promotable-rsc:0", cluster02, 0));
380  assert_null(native_find_rsc(promotable_1, "promotable-rsc:1", cluster01, 0));
381 
382  /* Check that the resource is running on the node we expect. */
383  assert_ptr_equal(promotable_0,
384  native_find_rsc(promotable_0, "promotable-rsc:0",
386  assert_null(native_find_rsc(promotable_0, "promotable-rsc:0", cluster01,
388  assert_ptr_equal(promotable_1,
389  native_find_rsc(promotable_1, "promotable-rsc:1",
391  assert_null(native_find_rsc(promotable_1, "promotable-rsc:1", cluster02,
393 
394  /* Passes because NULL was passed for node and primitive name was given, with correct flags. */
395  assert_ptr_equal(promotable_0,
396  native_find_rsc(promotable_0, "promotable-rsc", NULL,
398 
399  // Passes because pcmk_rsc_match_basename matches any instance's base name
400  assert_ptr_equal(promotable_0,
401  native_find_rsc(promotable_0, "promotable-rsc", NULL,
403  assert_ptr_equal(promotable_1,
404  native_find_rsc(promotable_1, "promotable-rsc", NULL,
406 
407  // Passes because pcmk_rsc_match_anon_basename matches
408  assert_ptr_equal(promotable_0,
409  native_find_rsc(promotable_0, "promotable-rsc", NULL,
411  assert_ptr_equal(promotable_1,
412  native_find_rsc(promotable_1, "promotable-rsc", NULL,
414 
415  /* Check that the resource is running on the node we expect. */
416  assert_ptr_equal(promotable_0,
417  native_find_rsc(promotable_0, "promotable-rsc", cluster02,
420  assert_ptr_equal(promotable_0,
421  native_find_rsc(promotable_0, "promotable-rsc", cluster02,
424  assert_null(native_find_rsc(promotable_0, "promotable-rsc", cluster01,
427  assert_null(native_find_rsc(promotable_0, "promotable-rsc", cluster01,
430  assert_ptr_equal(promotable_1,
431  native_find_rsc(promotable_1, "promotable-rsc", cluster01,
434  assert_ptr_equal(promotable_1,
435  native_find_rsc(promotable_1, "promotable-rsc", cluster01,
438  assert_null(native_find_rsc(promotable_1, "promotable-rsc", cluster02,
441  assert_null(native_find_rsc(promotable_1, "promotable-rsc", cluster02,
444 
445  /* Fails because incorrect flags were given along with primitive name. */
446  assert_null(native_find_rsc(promotable_0, "promotable-rsc", NULL,
448  assert_null(native_find_rsc(promotable_1, "promotable-rsc", NULL,
450 
451  /* And then we check failure possibilities again, except passing promotable_clone
452  * instead of promotable_X as the first argument to native_find_rsc.
453  */
454 
455  // Fails because pcmk_rsc_match_current_node is required if a node is given
456  assert_null(native_find_rsc(promotable_clone, "promotable-rsc:0", cluster02, 0));
457  assert_null(native_find_rsc(promotable_clone, "promotable-rsc:1", cluster01, 0));
458 
459  /* Check that the resource is running on the node we expect. */
460  assert_ptr_equal(promotable_0,
461  native_find_rsc(promotable_clone, "promotable-rsc:0",
463  assert_ptr_equal(promotable_0,
464  native_find_rsc(promotable_clone, "promotable-rsc",
465  cluster02,
468  assert_ptr_equal(promotable_0,
469  native_find_rsc(promotable_clone, "promotable-rsc",
470  cluster02,
473  assert_ptr_equal(promotable_1,
474  native_find_rsc(promotable_clone, "promotable-rsc:1",
476  assert_ptr_equal(promotable_1,
477  native_find_rsc(promotable_clone, "promotable-rsc",
478  cluster01,
481  assert_ptr_equal(promotable_1,
482  native_find_rsc(promotable_clone, "promotable-rsc",
483  cluster01,
486 }
487 
488 static void
489 renamed_rsc(void **state) {
492 
493  /* Find the "promotable-rsc:0" and "promotable-rsc:1" resources, members of "promotable-clone". */
494  for (GList *iter = promotable_clone->children; iter != NULL; iter = iter->next) {
495  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
496 
497  if (strcmp(rsc->id, "promotable-rsc:0") == 0) {
498  promotable_0 = rsc;
499  } else if (strcmp(rsc->id, "promotable-rsc:1") == 0) {
500  promotable_1 = rsc;
501  }
502  }
503 
504  assert_non_null(promotable_0);
505  assert_non_null(promotable_1);
506 
507  // Passes because pcmk_rsc_match_history means base name matches clone_name
508  assert_ptr_equal(promotable_0,
509  native_find_rsc(promotable_0, "promotable-rsc", NULL,
511  assert_ptr_equal(promotable_1,
512  native_find_rsc(promotable_1, "promotable-rsc", NULL,
514 }
515 
516 static void
517 bundle_rsc(void **state) {
518  assert_non_null(httpd_bundle);
519 
520  /* Passes because NULL was passed for node, regardless of flags. */
521  assert_ptr_equal(httpd_bundle, native_find_rsc(httpd_bundle, "httpd-bundle", NULL, 0));
522  assert_ptr_equal(httpd_bundle,
523  native_find_rsc(httpd_bundle, "httpd-bundle", NULL,
525 
526  /* Fails because resource is not a clone (nor cloned). */
527  assert_null(native_find_rsc(httpd_bundle, "httpd-bundle", NULL,
529  assert_null(native_find_rsc(httpd_bundle, "httpd-bundle", cluster01,
531 
532  // Fails because pcmk_rsc_match_current_node is required if a node is given
533  assert_null(native_find_rsc(httpd_bundle, "httpd-bundle", cluster01, 0));
534 
535  /* Passes because one of httpd_bundle's children is running on cluster01. */
536  assert_ptr_equal(httpd_bundle,
537  native_find_rsc(httpd_bundle, "httpd-bundle", cluster01,
539 }
540 
541 static bool
542 bundle_first_replica(pcmk__bundle_replica_t *replica, void *user_data)
543 {
544  pcmk_resource_t *ip_0 = replica->ip;
545  pcmk_resource_t *child_0 = replica->child;
546  pcmk_resource_t *container_0 = replica->container;
547  pcmk_resource_t *remote_0 = replica->remote;
548 
549  assert_non_null(ip_0);
550  assert_non_null(child_0);
551  assert_non_null(container_0);
552  assert_non_null(remote_0);
553 
554  /* Passes because NULL was passed for node, regardless of flags. */
555  assert_ptr_equal(ip_0, native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131", NULL, 0));
556  assert_ptr_equal(child_0, native_find_rsc(child_0, "httpd:0", NULL, 0));
557  assert_ptr_equal(container_0, native_find_rsc(container_0, "httpd-bundle-docker-0", NULL, 0));
558  assert_ptr_equal(remote_0, native_find_rsc(remote_0, "httpd-bundle-0", NULL, 0));
559 
560  // Fails because pcmk_rsc_match_current_node is required if a node is given
561  assert_null(native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131", cluster01, 0));
562  assert_null(native_find_rsc(child_0, "httpd:0", httpd_bundle_0, 0));
563  assert_null(native_find_rsc(container_0, "httpd-bundle-docker-0", cluster01, 0));
564  assert_null(native_find_rsc(remote_0, "httpd-bundle-0", cluster01, 0));
565 
566  /* Check that the resource is running on the node we expect. */
567  assert_ptr_equal(ip_0,
568  native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131",
570  assert_null(native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131",
572  assert_null(native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131",
574  assert_ptr_equal(child_0,
575  native_find_rsc(child_0, "httpd:0", httpd_bundle_0,
577  assert_null(native_find_rsc(child_0, "httpd:0", cluster01,
579  assert_null(native_find_rsc(child_0, "httpd:0", cluster02,
581  assert_ptr_equal(container_0,
582  native_find_rsc(container_0, "httpd-bundle-docker-0",
584  assert_null(native_find_rsc(container_0, "httpd-bundle-docker-0", cluster02,
586  assert_null(native_find_rsc(container_0, "httpd-bundle-docker-0",
588  assert_ptr_equal(remote_0,
589  native_find_rsc(remote_0, "httpd-bundle-0", cluster01,
591  assert_null(native_find_rsc(remote_0, "httpd-bundle-0", cluster02,
593  assert_null(native_find_rsc(remote_0, "httpd-bundle-0", httpd_bundle_0,
595 
596  // Passes because pcmk_rsc_match_basename matches any replica's base name
597  assert_ptr_equal(child_0,
598  native_find_rsc(child_0, "httpd", NULL,
600 
601  // Passes because pcmk_rsc_match_anon_basename matches
602  assert_ptr_equal(child_0,
603  native_find_rsc(child_0, "httpd", NULL,
605 
606  /* Check that the resource is running on the node we expect. */
607  assert_ptr_equal(child_0,
608  native_find_rsc(child_0, "httpd", httpd_bundle_0,
611  assert_ptr_equal(child_0,
612  native_find_rsc(child_0, "httpd", httpd_bundle_0,
615  assert_null(native_find_rsc(child_0, "httpd", cluster01,
618  assert_null(native_find_rsc(child_0, "httpd", cluster01,
621  assert_null(native_find_rsc(child_0, "httpd", cluster02,
624  assert_null(native_find_rsc(child_0, "httpd", cluster02,
627 
628  /* Fails because incorrect flags were given along with base name. */
629  assert_null(native_find_rsc(child_0, "httpd", NULL,
631 
632  /* And then we check failure possibilities again, except passing httpd-bundle
633  * instead of X_0 as the first argument to native_find_rsc.
634  */
635 
636  // Fails because pcmk_rsc_match_current_node is required if a node is given
637  assert_null(native_find_rsc(httpd_bundle, "httpd-bundle-ip-192.168.122.131", cluster01, 0));
638  assert_null(native_find_rsc(httpd_bundle, "httpd:0", httpd_bundle_0, 0));
639  assert_null(native_find_rsc(httpd_bundle, "httpd-bundle-docker-0", cluster01, 0));
640  assert_null(native_find_rsc(httpd_bundle, "httpd-bundle-0", cluster01, 0));
641 
642  /* Check that the resource is running on the node we expect. */
643  assert_ptr_equal(ip_0,
645  "httpd-bundle-ip-192.168.122.131",
647  assert_ptr_equal(child_0,
650  assert_ptr_equal(container_0,
651  native_find_rsc(httpd_bundle, "httpd-bundle-docker-0",
653  assert_ptr_equal(remote_0,
654  native_find_rsc(httpd_bundle, "httpd-bundle-0", cluster01,
656  return false; // Do not iterate through any further replicas
657 }
658 
659 static void
660 bundle_replica_rsc(void **state)
661 {
662  pe__foreach_bundle_replica(httpd_bundle, bundle_first_replica, NULL);
663 }
664 
665 static void
666 clone_group_rsc(void **rsc) {
667  assert_non_null(mysql_clone_group);
668 
669  /* Passes because NULL was passed for node, regardless of flags. */
670  assert_ptr_equal(mysql_clone_group, native_find_rsc(mysql_clone_group, "mysql-clone-group", NULL, 0));
671  assert_ptr_equal(mysql_clone_group,
672  native_find_rsc(mysql_clone_group, "mysql-clone-group",
674  assert_ptr_equal(mysql_clone_group,
675  native_find_rsc(mysql_clone_group, "mysql-clone-group",
677 
678  // Fails because pcmk_rsc_match_current_node is required if a node is given
679  assert_null(native_find_rsc(mysql_clone_group, "mysql-clone-group", cluster01, 0));
680 
681  /* Passes because one of mysql-clone-group's children is running on cluster01. */
682  assert_ptr_equal(mysql_clone_group,
683  native_find_rsc(mysql_clone_group, "mysql-clone-group",
685 
686  // Fails because pcmk_rsc_match_current_node is required if a node is given
687  assert_null(native_find_rsc(mysql_clone_group, "mysql-clone-group", cluster02, 0));
688 
689  /* Passes because one of mysql-clone-group's children is running on cluster02. */
690  assert_ptr_equal(mysql_clone_group,
691  native_find_rsc(mysql_clone_group, "mysql-clone-group",
693 
694  // Passes for previous reasons, plus includes pcmk_rsc_match_clone_only
695  assert_ptr_equal(mysql_clone_group,
696  native_find_rsc(mysql_clone_group, "mysql-clone-group",
697  cluster01,
700  assert_ptr_equal(mysql_clone_group,
701  native_find_rsc(mysql_clone_group, "mysql-clone-group",
702  cluster02,
705 }
706 
707 static void
708 clone_group_instance_rsc(void **rsc) {
711 
712  /* Find the "mysql-group:0" and "mysql-group:1" resources, members of "mysql-clone-group". */
713  for (GList *iter = mysql_clone_group->children; iter != NULL; iter = iter->next) {
714  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
715 
716  if (strcmp(rsc->id, "mysql-group:0") == 0) {
717  mysql_group_0 = rsc;
718  } else if (strcmp(rsc->id, "mysql-group:1") == 0) {
719  mysql_group_1 = rsc;
720  }
721  }
722 
723  assert_non_null(mysql_group_0);
724  assert_non_null(mysql_group_1);
725 
726  /* Passes because NULL was passed for node, regardless of flags. */
727  assert_ptr_equal(mysql_group_0, native_find_rsc(mysql_group_0, "mysql-group:0", NULL, 0));
728  assert_ptr_equal(mysql_group_0,
729  native_find_rsc(mysql_group_0, "mysql-group:0", NULL,
731  assert_ptr_equal(mysql_group_1, native_find_rsc(mysql_group_1, "mysql-group:1", NULL, 0));
732  assert_ptr_equal(mysql_group_1,
733  native_find_rsc(mysql_group_1, "mysql-group:1", NULL,
735 
736  // Fails because pcmk_rsc_match_current_node is required if a node is given
737  assert_null(native_find_rsc(mysql_group_0, "mysql-group:0", cluster02, 0));
738  assert_null(native_find_rsc(mysql_group_1, "mysql-group:1", cluster01, 0));
739 
740  /* Check that the resource is running on the node we expect. */
741  assert_ptr_equal(mysql_group_0,
742  native_find_rsc(mysql_group_0, "mysql-group:0", cluster02,
744  assert_null(native_find_rsc(mysql_group_0, "mysql-group:0", cluster01,
746  assert_ptr_equal(mysql_group_1,
747  native_find_rsc(mysql_group_1, "mysql-group:1", cluster01,
749  assert_null(native_find_rsc(mysql_group_1, "mysql-group:1", cluster02,
751 
752  /* Passes because NULL was passed for node and base name was given, with correct flags. */
753  assert_ptr_equal(mysql_group_0,
754  native_find_rsc(mysql_group_0, "mysql-group" , NULL,
756 
757  // Passes because pcmk_rsc_match_basename matches any base name
758  assert_ptr_equal(mysql_group_0,
759  native_find_rsc(mysql_group_0, "mysql-group" , NULL,
761  assert_ptr_equal(mysql_group_1,
762  native_find_rsc(mysql_group_1, "mysql-group" , NULL,
764 
765  // Passes because pcmk_rsc_match_anon_basename matches
766  assert_ptr_equal(mysql_group_0,
767  native_find_rsc(mysql_group_0, "mysql-group" , NULL,
769  assert_ptr_equal(mysql_group_1,
770  native_find_rsc(mysql_group_1, "mysql-group" , NULL,
772 
773  /* Check that the resource is running on the node we expect. */
774  assert_ptr_equal(mysql_group_0,
775  native_find_rsc(mysql_group_0, "mysql-group", cluster02,
778  assert_ptr_equal(mysql_group_0,
779  native_find_rsc(mysql_group_0, "mysql-group", cluster02,
782  assert_null(native_find_rsc(mysql_group_0, "mysql-group", cluster01,
785  assert_null(native_find_rsc(mysql_group_0, "mysql-group", cluster01,
788  assert_ptr_equal(mysql_group_1,
789  native_find_rsc(mysql_group_1, "mysql-group", cluster01,
792  assert_ptr_equal(mysql_group_1,
793  native_find_rsc(mysql_group_1, "mysql-group", cluster01,
796  assert_null(native_find_rsc(mysql_group_1, "mysql-group", cluster02,
799  assert_null(native_find_rsc(mysql_group_1, "mysql-group", cluster02,
802 
803  /* Fails because incorrect flags were given along with base name. */
804  assert_null(native_find_rsc(mysql_group_0, "mysql-group", NULL,
806  assert_null(native_find_rsc(mysql_group_1, "mysql-group", NULL,
808 
809  /* And then we check failure possibilities again, except passing mysql_clone_group
810  * instead of mysql_group_X as the first argument to native_find_rsc.
811  */
812 
813  // Fails because pcmk_rsc_match_current_node is required if a node is given
814  assert_null(native_find_rsc(mysql_clone_group, "mysql-group:0", cluster02, 0));
815  assert_null(native_find_rsc(mysql_clone_group, "mysql-group:1", cluster01, 0));
816 
817  /* Check that the resource is running on the node we expect. */
818  assert_ptr_equal(mysql_group_0,
819  native_find_rsc(mysql_clone_group, "mysql-group:0",
821  assert_ptr_equal(mysql_group_0,
822  native_find_rsc(mysql_clone_group, "mysql-group",
823  cluster02,
826  assert_ptr_equal(mysql_group_0,
827  native_find_rsc(mysql_clone_group, "mysql-group",
828  cluster02,
831  assert_ptr_equal(mysql_group_1,
832  native_find_rsc(mysql_clone_group, "mysql-group:1",
834  assert_ptr_equal(mysql_group_1,
835  native_find_rsc(mysql_clone_group, "mysql-group",
836  cluster01,
839  assert_ptr_equal(mysql_group_1,
840  native_find_rsc(mysql_clone_group, "mysql-group",
841  cluster01,
844 }
845 
846 static void
847 clone_group_member_rsc(void **state) {
848  pcmk_resource_t *mysql_proxy = NULL;
849 
850  /* Find the "mysql-proxy" resource, a member of "mysql-group". */
851  for (GList *iter = mysql_clone_group->children; iter != NULL; iter = iter->next) {
852  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
853 
854  if (strcmp(rsc->id, "mysql-group:0") == 0) {
855  for (GList *iter2 = rsc->children; iter2 != NULL; iter2 = iter2->next) {
856  pcmk_resource_t *child = (pcmk_resource_t *) iter2->data;
857 
858  if (strcmp(child->id, "mysql-proxy:0") == 0) {
859  mysql_proxy = child;
860  break;
861  }
862  }
863 
864  break;
865  }
866  }
867 
868  assert_non_null(mysql_proxy);
869 
870  /* Passes because NULL was passed for node, regardless of flags. */
871  assert_ptr_equal(mysql_proxy, native_find_rsc(mysql_proxy, "mysql-proxy:0", NULL, 0));
872  assert_ptr_equal(mysql_proxy,
873  native_find_rsc(mysql_proxy, "mysql-proxy:0", NULL,
875 
876  /* Passes because resource's parent is a clone. */
877  assert_ptr_equal(mysql_proxy,
878  native_find_rsc(mysql_proxy, "mysql-proxy:0", NULL,
880  assert_ptr_equal(mysql_proxy,
881  native_find_rsc(mysql_proxy, "mysql-proxy:0", cluster02,
884 
885  /* Fails because mysql-proxy:0 is not running on cluster01, even with the right flags. */
886  assert_null(native_find_rsc(mysql_proxy, "mysql-proxy:0", cluster01,
888 
889  // Fails because pcmk_rsc_match_current_node is required if a node is given
890  assert_null(native_find_rsc(mysql_proxy, "mysql-proxy:0", cluster02, 0));
891 
892  /* Passes because mysql-proxy:0 is running on cluster02. */
893  assert_ptr_equal(mysql_proxy,
894  native_find_rsc(mysql_proxy, "mysql-proxy:0", cluster02,
896 }
897 
898 /* TODO: Add tests for finding on assigned node (passing a node without
899  * pcmk_rsc_match_current_node, after scheduling, for a resource that is
900  * starting/stopping/moving.
901  */
902 PCMK__UNIT_TEST(setup, teardown,
903  cmocka_unit_test(bad_args),
904  cmocka_unit_test(primitive_rsc),
905  cmocka_unit_test(group_rsc),
906  cmocka_unit_test(inactive_group_rsc),
907  cmocka_unit_test(group_member_rsc),
908  cmocka_unit_test(inactive_group_member_rsc),
909  cmocka_unit_test(clone_rsc),
910  cmocka_unit_test(inactive_clone_rsc),
911  cmocka_unit_test(clone_instance_rsc),
912  cmocka_unit_test(renamed_rsc),
913  cmocka_unit_test(bundle_rsc),
914  cmocka_unit_test(bundle_replica_rsc),
915  cmocka_unit_test(clone_group_rsc),
916  cmocka_unit_test(clone_group_instance_rsc),
917  cmocka_unit_test(clone_group_member_rsc))
pcmk_resource_t * inactive_group
pcmk_node_t * pcmk_find_node(const pcmk_scheduler_t *scheduler, const char *node_name)
Find a node by name in scheduler data.
Definition: scheduler.c:103
Also match anonymous clone instances by base name.
Definition: resources.h:188
pcmk_resource_t * dummy
const char * name
Definition: cib.c:26
pcmk_node_t * cluster01
GList * children
Definition: resources.h:471
Match only clones and their instances, by either clone or instance ID.
Definition: resources.h:191
void pe__foreach_bundle_replica(pcmk_resource_t *bundle, bool(*fn)(pcmk__bundle_replica_t *, void *), void *user_data)
Definition: bundle.c:208
pcmk_resource_t * ip
IP address resource for ipaddr.
void crm_xml_init(void)
Initialize the CRM XML subsystem.
Definition: xml.c:2121
pcmk_resource_t * inactive_clone
#define PCMK__UNIT_TEST(group_setup, group_teardown,...)
gboolean cluster_status(pcmk_scheduler_t *scheduler)
Definition: status.c:96
GList * resources
Definition: scheduler.h:231
Scheduler API.
Also match clone instance ID from resource history.
Definition: resources.h:185
pcmk_resource_t * promotable_0
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
Wrappers for and extensions to libxml2.
Match clone instances (even unique) by base name as well as exact ID.
Definition: resources.h:200
pcmk_resource_t * mysql_clone_group
xmlNode * input
Definition: scheduler.h:196
pcmk_resource_t * child
Instance of bundled resource.
pcmk_scheduler_t * pe_new_working_set(void)
Create a new object to hold scheduler data.
Definition: status.c:34
uint32_t id
Definition: cpg.c:48
pcmk_node_t * httpd_bundle_0
A single instance of a bundle.
xmlNode * pcmk__xml_read(const char *filename)
Definition: xml_io.c:166
void pe_free_working_set(pcmk_scheduler_t *scheduler)
Free scheduler data.
Definition: status.c:50
pcmk_resource_t * mysql_group_1
pcmk_resource_t * native_find_rsc(pcmk_resource_t *rsc, const char *id, const pcmk_node_t *node, int flags)
Definition: native.c:271
pcmk_resource_t * container
Container associated with this instance.
Cluster status and scheduling.
const char * path
Definition: cib.c:28
pcmk_scheduler_t * scheduler
If matching by node, compare current node instead of assigned node.
Definition: resources.h:194
pcmk_node_t * cluster02
xmlNode * input
pcmk_resource_t * httpd_bundle
pcmk_resource_t * promotable_1
pcmk_resource_t * promotable_clone
pcmk_resource_t * exim_group
pcmk_resource_t * remote
Pacemaker Remote connection into container.
#define pcmk__set_scheduler_flags(scheduler, flags_to_set)
pcmk_resource_t * mysql_group_0