pacemaker  3.0.0-d8340737c4
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 
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 
48 
50 
51  /* Get references to the cluster nodes so we don't have to find them repeatedly. */
52  cluster01 = pcmk_find_node(scheduler, "cluster01");
53  cluster02 = pcmk_find_node(scheduler, "cluster02");
54  httpd_bundle_0 = pcmk_find_node(scheduler, "httpd-bundle-0");
55 
56  /* Get references to several resources we use frequently. */
57  for (GList *iter = scheduler->priv->resources;
58  iter != NULL; iter = iter->next) {
59 
60  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
61 
62  if (strcmp(rsc->id, "exim-group") == 0) {
63  exim_group = rsc;
64  } else if (strcmp(rsc->id, "httpd-bundle") == 0) {
65  httpd_bundle = rsc;
66  } else if (strcmp(rsc->id, "inactive-clone") == 0) {
67  inactive_clone = rsc;
68  } else if (strcmp(rsc->id, "inactive-group") == 0) {
69  inactive_group = rsc;
70  } else if (strcmp(rsc->id, "mysql-clone-group") == 0) {
71  mysql_clone_group = rsc;
72  } else if (strcmp(rsc->id, "promotable-clone") == 0) {
73  promotable_clone = rsc;
74  }
75  }
76 
77  return 0;
78 }
79 
80 static int
81 teardown(void **state) {
84  return 0;
85 }
86 
87 static void
88 bad_args(void **state) {
89  pcmk_resource_t *rsc = g_list_first(scheduler->priv->resources)->data;
90  char *id = rsc->id;
91  char *name = NULL;
92 
93  assert_non_null(rsc);
94 
95  assert_null(native_find_rsc(NULL, "dummy", NULL, 0));
96  assert_null(native_find_rsc(rsc, NULL, NULL, 0));
97 
98  /* No resources exist with these names. */
99  name = crm_strdup_printf("%sX", rsc->id);
100  assert_null(native_find_rsc(rsc, name, NULL, 0));
101  free(name);
102 
103  name = crm_strdup_printf("x%s", rsc->id);
104  assert_null(native_find_rsc(rsc, name, NULL, 0));
105  free(name);
106 
107  name = g_ascii_strup(rsc->id, -1);
108  assert_null(native_find_rsc(rsc, name, NULL, 0));
109  g_free(name);
110 
111  /* Fails because resource ID is NULL. */
112  rsc->id = NULL;
113  assert_null(native_find_rsc(rsc, id, NULL, 0));
114  rsc->id = id;
115 }
116 
117 static void
118 primitive_rsc(void **state) {
119  pcmk_resource_t *dummy = NULL;
120 
121  /* Find the "dummy" resource, which is the only one with that ID in the set. */
122  for (GList *iter = scheduler->priv->resources;
123  iter != NULL; iter = iter->next) {
124 
125  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
126 
127  if (strcmp(rsc->id, "dummy") == 0) {
128  dummy = rsc;
129  break;
130  }
131  }
132 
133  assert_non_null(dummy);
134 
135  /* Passes because NULL was passed for node, regardless of flags. */
136  assert_ptr_equal(dummy, native_find_rsc(dummy, "dummy", NULL, 0));
137  assert_ptr_equal(dummy,
138  native_find_rsc(dummy, "dummy", NULL,
140 
141  /* Fails because resource is not a clone (nor cloned). */
142  assert_null(native_find_rsc(dummy, "dummy", NULL,
144  assert_null(native_find_rsc(dummy, "dummy", cluster02,
146 
147  /* Fails because dummy is not running on cluster01, even with the right flags. */
148  assert_null(native_find_rsc(dummy, "dummy", cluster01,
150 
151  // Fails because pcmk_rsc_match_current_node is required if a node is given
152  assert_null(native_find_rsc(dummy, "dummy", cluster02, 0));
153 
154  /* Passes because dummy is running on cluster02. */
155  assert_ptr_equal(dummy,
156  native_find_rsc(dummy, "dummy", cluster02,
158 }
159 
160 static void
161 group_rsc(void **state) {
162  assert_non_null(exim_group);
163 
164  /* Passes because NULL was passed for node, regardless of flags. */
165  assert_ptr_equal(exim_group, native_find_rsc(exim_group, "exim-group", NULL, 0));
166  assert_ptr_equal(exim_group,
167  native_find_rsc(exim_group, "exim-group", NULL,
169 
170  /* Fails because resource is not a clone (nor cloned). */
171  assert_null(native_find_rsc(exim_group, "exim-group", NULL,
173  assert_null(native_find_rsc(exim_group, "exim-group", cluster01,
175 
176  /* Fails because none of exim-group's children are running on cluster01, even with the right flags. */
177  assert_null(native_find_rsc(exim_group, "exim-group", cluster01,
179 
180  // Fails because pcmk_rsc_match_current_node is required if a node is given
181  assert_null(native_find_rsc(exim_group, "exim-group", cluster01, 0));
182 
183  /* Passes because one of exim-group's children is running on cluster02. */
184  assert_ptr_equal(exim_group,
185  native_find_rsc(exim_group, "exim-group", cluster02,
187 }
188 
189 static void
190 inactive_group_rsc(void **state) {
191  assert_non_null(inactive_group);
192 
193  /* Passes because NULL was passed for node, regardless of flags. */
194  assert_ptr_equal(inactive_group, native_find_rsc(inactive_group, "inactive-group", NULL, 0));
195  assert_ptr_equal(inactive_group,
196  native_find_rsc(inactive_group, "inactive-group", NULL,
198 
199  /* Fails because resource is not a clone (nor cloned). */
200  assert_null(native_find_rsc(inactive_group, "inactive-group", NULL,
202  assert_null(native_find_rsc(inactive_group, "inactive-group", cluster01,
204 
205  /* Fails because none of inactive-group's children are running. */
206  assert_null(native_find_rsc(inactive_group, "inactive-group", cluster01,
208  assert_null(native_find_rsc(inactive_group, "inactive-group", cluster02,
210 }
211 
212 static void
213 group_member_rsc(void **state) {
214  pcmk_resource_t *public_ip = NULL;
215 
216  /* Find the "Public-IP" resource, a member of "exim-group". */
217  for (GList *iter = exim_group->priv->children;
218  iter != NULL; iter = iter->next) {
219 
220  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
221 
222  if (strcmp(rsc->id, "Public-IP") == 0) {
223  public_ip = rsc;
224  break;
225  }
226  }
227 
228  assert_non_null(public_ip);
229 
230  /* Passes because NULL was passed for node, regardless of flags. */
231  assert_ptr_equal(public_ip, native_find_rsc(public_ip, "Public-IP", NULL, 0));
232  assert_ptr_equal(public_ip,
233  native_find_rsc(public_ip, "Public-IP", NULL,
235 
236  /* Fails because resource is not a clone (nor cloned). */
237  assert_null(native_find_rsc(public_ip, "Public-IP", NULL,
239  assert_null(native_find_rsc(public_ip, "Public-IP", cluster02,
241 
242  /* Fails because Public-IP is not running on cluster01, even with the right flags. */
243  assert_null(native_find_rsc(public_ip, "Public-IP", cluster01,
245 
246  // Fails because pcmk_rsc_match_current_node is required if a node is given
247  assert_null(native_find_rsc(public_ip, "Public-IP", cluster02, 0));
248 
249  /* Passes because Public-IP is running on cluster02. */
250  assert_ptr_equal(public_ip,
251  native_find_rsc(public_ip, "Public-IP", cluster02,
253 }
254 
255 static void
256 inactive_group_member_rsc(void **state) {
257  pcmk_resource_t *inactive_dummy_1 = NULL;
258 
259  /* Find the "inactive-dummy-1" resource, a member of "inactive-group". */
260  for (GList *iter = inactive_group->priv->children;
261  iter != NULL; iter = iter->next) {
262 
263  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
264 
265  if (strcmp(rsc->id, "inactive-dummy-1") == 0) {
266  inactive_dummy_1 = rsc;
267  break;
268  }
269  }
270 
271  assert_non_null(inactive_dummy_1);
272 
273  /* Passes because NULL was passed for node, regardless of flags. */
274  assert_ptr_equal(inactive_dummy_1, native_find_rsc(inactive_dummy_1, "inactive-dummy-1", NULL, 0));
275  assert_ptr_equal(inactive_dummy_1,
276  native_find_rsc(inactive_dummy_1, "inactive-dummy-1", NULL,
278 
279  /* Fails because resource is not a clone (nor cloned). */
280  assert_null(native_find_rsc(inactive_dummy_1, "inactive-dummy-1", NULL,
282  assert_null(native_find_rsc(inactive_dummy_1, "inactive-dummy-1", cluster01,
284 
285  /* Fails because inactive-dummy-1 is not running. */
286  assert_null(native_find_rsc(inactive_dummy_1, "inactive-dummy-1", cluster01,
288  assert_null(native_find_rsc(inactive_dummy_1, "inactive-dummy-1", cluster02,
290 }
291 
292 static void
293 clone_rsc(void **state) {
294  assert_non_null(promotable_clone);
295 
296  /* Passes because NULL was passed for node, regardless of flags. */
297  assert_ptr_equal(promotable_clone, native_find_rsc(promotable_clone, "promotable-clone", NULL, 0));
298  assert_ptr_equal(promotable_clone,
299  native_find_rsc(promotable_clone, "promotable-clone", NULL,
301  assert_ptr_equal(promotable_clone,
302  native_find_rsc(promotable_clone, "promotable-clone", NULL,
304 
305  // Fails because pcmk_rsc_match_current_node is required if a node is given
306  assert_null(native_find_rsc(promotable_clone, "promotable-clone", cluster01, 0));
307 
308  /* Passes because one of ping-clone's children is running on cluster01. */
309  assert_ptr_equal(promotable_clone,
310  native_find_rsc(promotable_clone, "promotable-clone",
312 
313  // Fails because pcmk_rsc_match_current_node is required if a node is given
314  assert_null(native_find_rsc(promotable_clone, "promotable-clone", cluster02, 0));
315 
316  /* Passes because one of ping_clone's children is running on cluster02. */
317  assert_ptr_equal(promotable_clone,
318  native_find_rsc(promotable_clone, "promotable-clone",
320 
321  // Passes for previous reasons, plus includes pcmk_rsc_match_clone_only
322  assert_ptr_equal(promotable_clone,
323  native_find_rsc(promotable_clone, "promotable-clone",
324  cluster01,
327  assert_ptr_equal(promotable_clone,
328  native_find_rsc(promotable_clone, "promotable-clone",
329  cluster02,
332 }
333 
334 static void
335 inactive_clone_rsc(void **state) {
336  assert_non_null(inactive_clone);
337 
338  /* Passes because NULL was passed for node, regardless of flags. */
339  assert_ptr_equal(inactive_clone, native_find_rsc(inactive_clone, "inactive-clone", NULL, 0));
340  assert_ptr_equal(inactive_clone,
341  native_find_rsc(inactive_clone, "inactive-clone", NULL,
343  assert_ptr_equal(inactive_clone,
344  native_find_rsc(inactive_clone, "inactive-clone", NULL,
346 
347  /* Fails because none of inactive-clone's children are running. */
348  assert_null(native_find_rsc(inactive_clone, "inactive-clone", cluster01,
351  assert_null(native_find_rsc(inactive_clone, "inactive-clone", cluster02,
354 }
355 
356 static void
357 clone_instance_rsc(void **state) {
360 
361  /* Find the "promotable-rsc:0" and "promotable-rsc:1" resources, members of "promotable-clone". */
362  for (GList *iter = promotable_clone->priv->children;
363  iter != NULL; iter = iter->next) {
364 
365  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
366 
367  if (strcmp(rsc->id, "promotable-rsc:0") == 0) {
368  promotable_0 = rsc;
369  } else if (strcmp(rsc->id, "promotable-rsc:1") == 0) {
370  promotable_1 = rsc;
371  }
372  }
373 
374  assert_non_null(promotable_0);
375  assert_non_null(promotable_1);
376 
377  /* Passes because NULL was passed for node, regardless of flags. */
378  assert_ptr_equal(promotable_0, native_find_rsc(promotable_0, "promotable-rsc:0", NULL, 0));
379  assert_ptr_equal(promotable_0,
380  native_find_rsc(promotable_0, "promotable-rsc:0", NULL,
382  assert_ptr_equal(promotable_1, native_find_rsc(promotable_1, "promotable-rsc:1", NULL, 0));
383  assert_ptr_equal(promotable_1,
384  native_find_rsc(promotable_1, "promotable-rsc:1", NULL,
386 
387  // Fails because pcmk_rsc_match_current_node is required if a node is given
388  assert_null(native_find_rsc(promotable_0, "promotable-rsc:0", cluster02, 0));
389  assert_null(native_find_rsc(promotable_1, "promotable-rsc:1", cluster01, 0));
390 
391  /* Check that the resource is running on the node we expect. */
392  assert_ptr_equal(promotable_0,
393  native_find_rsc(promotable_0, "promotable-rsc:0",
395  assert_null(native_find_rsc(promotable_0, "promotable-rsc:0", cluster01,
397  assert_ptr_equal(promotable_1,
398  native_find_rsc(promotable_1, "promotable-rsc:1",
400  assert_null(native_find_rsc(promotable_1, "promotable-rsc:1", cluster02,
402 
403  /* Passes because NULL was passed for node and primitive name was given, with correct flags. */
404  assert_ptr_equal(promotable_0,
405  native_find_rsc(promotable_0, "promotable-rsc", NULL,
407 
408  // Passes because pcmk_rsc_match_basename matches any instance's base name
409  assert_ptr_equal(promotable_0,
410  native_find_rsc(promotable_0, "promotable-rsc", NULL,
412  assert_ptr_equal(promotable_1,
413  native_find_rsc(promotable_1, "promotable-rsc", NULL,
415 
416  // Passes because pcmk_rsc_match_anon_basename matches
417  assert_ptr_equal(promotable_0,
418  native_find_rsc(promotable_0, "promotable-rsc", NULL,
420  assert_ptr_equal(promotable_1,
421  native_find_rsc(promotable_1, "promotable-rsc", NULL,
423 
424  /* Check that the resource is running on the node we expect. */
425  assert_ptr_equal(promotable_0,
426  native_find_rsc(promotable_0, "promotable-rsc", cluster02,
429  assert_ptr_equal(promotable_0,
430  native_find_rsc(promotable_0, "promotable-rsc", cluster02,
433  assert_null(native_find_rsc(promotable_0, "promotable-rsc", cluster01,
436  assert_null(native_find_rsc(promotable_0, "promotable-rsc", cluster01,
439  assert_ptr_equal(promotable_1,
440  native_find_rsc(promotable_1, "promotable-rsc", cluster01,
443  assert_ptr_equal(promotable_1,
444  native_find_rsc(promotable_1, "promotable-rsc", cluster01,
447  assert_null(native_find_rsc(promotable_1, "promotable-rsc", cluster02,
450  assert_null(native_find_rsc(promotable_1, "promotable-rsc", cluster02,
453 
454  /* Fails because incorrect flags were given along with primitive name. */
455  assert_null(native_find_rsc(promotable_0, "promotable-rsc", NULL,
457  assert_null(native_find_rsc(promotable_1, "promotable-rsc", NULL,
459 
460  /* And then we check failure possibilities again, except passing promotable_clone
461  * instead of promotable_X as the first argument to native_find_rsc.
462  */
463 
464  // Fails because pcmk_rsc_match_current_node is required if a node is given
465  assert_null(native_find_rsc(promotable_clone, "promotable-rsc:0", cluster02, 0));
466  assert_null(native_find_rsc(promotable_clone, "promotable-rsc:1", cluster01, 0));
467 
468  /* Check that the resource is running on the node we expect. */
469  assert_ptr_equal(promotable_0,
470  native_find_rsc(promotable_clone, "promotable-rsc:0",
472  assert_ptr_equal(promotable_0,
473  native_find_rsc(promotable_clone, "promotable-rsc",
474  cluster02,
477  assert_ptr_equal(promotable_0,
478  native_find_rsc(promotable_clone, "promotable-rsc",
479  cluster02,
482  assert_ptr_equal(promotable_1,
483  native_find_rsc(promotable_clone, "promotable-rsc:1",
485  assert_ptr_equal(promotable_1,
486  native_find_rsc(promotable_clone, "promotable-rsc",
487  cluster01,
490  assert_ptr_equal(promotable_1,
491  native_find_rsc(promotable_clone, "promotable-rsc",
492  cluster01,
495 }
496 
497 static void
498 renamed_rsc(void **state) {
501 
502  /* Find the "promotable-rsc:0" and "promotable-rsc:1" resources, members of "promotable-clone". */
503  for (GList *iter = promotable_clone->priv->children;
504  iter != NULL; iter = iter->next) {
505 
506  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
507 
508  if (strcmp(rsc->id, "promotable-rsc:0") == 0) {
509  promotable_0 = rsc;
510  } else if (strcmp(rsc->id, "promotable-rsc:1") == 0) {
511  promotable_1 = rsc;
512  }
513  }
514 
515  assert_non_null(promotable_0);
516  assert_non_null(promotable_1);
517 
518  // Passes because pcmk_rsc_match_history means base name matches history_id
519  assert_ptr_equal(promotable_0,
520  native_find_rsc(promotable_0, "promotable-rsc", NULL,
522  assert_ptr_equal(promotable_1,
523  native_find_rsc(promotable_1, "promotable-rsc", NULL,
525 }
526 
527 static void
528 bundle_rsc(void **state) {
529  assert_non_null(httpd_bundle);
530 
531  /* Passes because NULL was passed for node, regardless of flags. */
532  assert_ptr_equal(httpd_bundle, native_find_rsc(httpd_bundle, "httpd-bundle", NULL, 0));
533  assert_ptr_equal(httpd_bundle,
534  native_find_rsc(httpd_bundle, "httpd-bundle", NULL,
536 
537  /* Fails because resource is not a clone (nor cloned). */
538  assert_null(native_find_rsc(httpd_bundle, "httpd-bundle", NULL,
540  assert_null(native_find_rsc(httpd_bundle, "httpd-bundle", cluster01,
542 
543  // Fails because pcmk_rsc_match_current_node is required if a node is given
544  assert_null(native_find_rsc(httpd_bundle, "httpd-bundle", cluster01, 0));
545 
546  /* Passes because one of httpd_bundle's children is running on cluster01. */
547  assert_ptr_equal(httpd_bundle,
548  native_find_rsc(httpd_bundle, "httpd-bundle", cluster01,
550 }
551 
552 static bool
553 bundle_first_replica(pcmk__bundle_replica_t *replica, void *user_data)
554 {
555  pcmk_resource_t *ip_0 = replica->ip;
556  pcmk_resource_t *child_0 = replica->child;
557  pcmk_resource_t *container_0 = replica->container;
558  pcmk_resource_t *remote_0 = replica->remote;
559 
560  assert_non_null(ip_0);
561  assert_non_null(child_0);
562  assert_non_null(container_0);
563  assert_non_null(remote_0);
564 
565  /* Passes because NULL was passed for node, regardless of flags. */
566  assert_ptr_equal(ip_0, native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131", NULL, 0));
567  assert_ptr_equal(child_0, native_find_rsc(child_0, "httpd:0", NULL, 0));
568  assert_ptr_equal(container_0, native_find_rsc(container_0, "httpd-bundle-docker-0", NULL, 0));
569  assert_ptr_equal(remote_0, native_find_rsc(remote_0, "httpd-bundle-0", NULL, 0));
570 
571  // Fails because pcmk_rsc_match_current_node is required if a node is given
572  assert_null(native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131", cluster01, 0));
573  assert_null(native_find_rsc(child_0, "httpd:0", httpd_bundle_0, 0));
574  assert_null(native_find_rsc(container_0, "httpd-bundle-docker-0", cluster01, 0));
575  assert_null(native_find_rsc(remote_0, "httpd-bundle-0", cluster01, 0));
576 
577  /* Check that the resource is running on the node we expect. */
578  assert_ptr_equal(ip_0,
579  native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131",
581  assert_null(native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131",
583  assert_null(native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131",
585  assert_ptr_equal(child_0,
586  native_find_rsc(child_0, "httpd:0", httpd_bundle_0,
588  assert_null(native_find_rsc(child_0, "httpd:0", cluster01,
590  assert_null(native_find_rsc(child_0, "httpd:0", cluster02,
592  assert_ptr_equal(container_0,
593  native_find_rsc(container_0, "httpd-bundle-docker-0",
595  assert_null(native_find_rsc(container_0, "httpd-bundle-docker-0", cluster02,
597  assert_null(native_find_rsc(container_0, "httpd-bundle-docker-0",
599  assert_ptr_equal(remote_0,
600  native_find_rsc(remote_0, "httpd-bundle-0", cluster01,
602  assert_null(native_find_rsc(remote_0, "httpd-bundle-0", cluster02,
604  assert_null(native_find_rsc(remote_0, "httpd-bundle-0", httpd_bundle_0,
606 
607  // Passes because pcmk_rsc_match_basename matches any replica's base name
608  assert_ptr_equal(child_0,
609  native_find_rsc(child_0, "httpd", NULL,
611 
612  // Passes because pcmk_rsc_match_anon_basename matches
613  assert_ptr_equal(child_0,
614  native_find_rsc(child_0, "httpd", NULL,
616 
617  /* Check that the resource is running on the node we expect. */
618  assert_ptr_equal(child_0,
619  native_find_rsc(child_0, "httpd", httpd_bundle_0,
622  assert_ptr_equal(child_0,
623  native_find_rsc(child_0, "httpd", httpd_bundle_0,
626  assert_null(native_find_rsc(child_0, "httpd", cluster01,
629  assert_null(native_find_rsc(child_0, "httpd", cluster01,
632  assert_null(native_find_rsc(child_0, "httpd", cluster02,
635  assert_null(native_find_rsc(child_0, "httpd", cluster02,
638 
639  /* Fails because incorrect flags were given along with base name. */
640  assert_null(native_find_rsc(child_0, "httpd", NULL,
642 
643  /* And then we check failure possibilities again, except passing httpd-bundle
644  * instead of X_0 as the first argument to native_find_rsc.
645  */
646 
647  // Fails because pcmk_rsc_match_current_node is required if a node is given
648  assert_null(native_find_rsc(httpd_bundle, "httpd-bundle-ip-192.168.122.131", cluster01, 0));
649  assert_null(native_find_rsc(httpd_bundle, "httpd:0", httpd_bundle_0, 0));
650  assert_null(native_find_rsc(httpd_bundle, "httpd-bundle-docker-0", cluster01, 0));
651  assert_null(native_find_rsc(httpd_bundle, "httpd-bundle-0", cluster01, 0));
652 
653  /* Check that the resource is running on the node we expect. */
654  assert_ptr_equal(ip_0,
656  "httpd-bundle-ip-192.168.122.131",
658  assert_ptr_equal(child_0,
661  assert_ptr_equal(container_0,
662  native_find_rsc(httpd_bundle, "httpd-bundle-docker-0",
664  assert_ptr_equal(remote_0,
665  native_find_rsc(httpd_bundle, "httpd-bundle-0", cluster01,
667  return false; // Do not iterate through any further replicas
668 }
669 
670 static void
671 bundle_replica_rsc(void **state)
672 {
673  pe__foreach_bundle_replica(httpd_bundle, bundle_first_replica, NULL);
674 }
675 
676 static void
677 clone_group_rsc(void **rsc) {
678  assert_non_null(mysql_clone_group);
679 
680  /* Passes because NULL was passed for node, regardless of flags. */
681  assert_ptr_equal(mysql_clone_group, native_find_rsc(mysql_clone_group, "mysql-clone-group", NULL, 0));
682  assert_ptr_equal(mysql_clone_group,
683  native_find_rsc(mysql_clone_group, "mysql-clone-group",
685  assert_ptr_equal(mysql_clone_group,
686  native_find_rsc(mysql_clone_group, "mysql-clone-group",
688 
689  // Fails because pcmk_rsc_match_current_node is required if a node is given
690  assert_null(native_find_rsc(mysql_clone_group, "mysql-clone-group", cluster01, 0));
691 
692  /* Passes because one of mysql-clone-group's children is running on cluster01. */
693  assert_ptr_equal(mysql_clone_group,
694  native_find_rsc(mysql_clone_group, "mysql-clone-group",
696 
697  // Fails because pcmk_rsc_match_current_node is required if a node is given
698  assert_null(native_find_rsc(mysql_clone_group, "mysql-clone-group", cluster02, 0));
699 
700  /* Passes because one of mysql-clone-group's children is running on cluster02. */
701  assert_ptr_equal(mysql_clone_group,
702  native_find_rsc(mysql_clone_group, "mysql-clone-group",
704 
705  // Passes for previous reasons, plus includes pcmk_rsc_match_clone_only
706  assert_ptr_equal(mysql_clone_group,
707  native_find_rsc(mysql_clone_group, "mysql-clone-group",
708  cluster01,
711  assert_ptr_equal(mysql_clone_group,
712  native_find_rsc(mysql_clone_group, "mysql-clone-group",
713  cluster02,
716 }
717 
718 static void
719 clone_group_instance_rsc(void **rsc) {
722 
723  /* Find the "mysql-group:0" and "mysql-group:1" resources, members of "mysql-clone-group". */
724  for (GList *iter = mysql_clone_group->priv->children;
725  iter != NULL; iter = iter->next) {
726 
727  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
728 
729  if (strcmp(rsc->id, "mysql-group:0") == 0) {
730  mysql_group_0 = rsc;
731  } else if (strcmp(rsc->id, "mysql-group:1") == 0) {
732  mysql_group_1 = rsc;
733  }
734  }
735 
736  assert_non_null(mysql_group_0);
737  assert_non_null(mysql_group_1);
738 
739  /* Passes because NULL was passed for node, regardless of flags. */
740  assert_ptr_equal(mysql_group_0, native_find_rsc(mysql_group_0, "mysql-group:0", NULL, 0));
741  assert_ptr_equal(mysql_group_0,
742  native_find_rsc(mysql_group_0, "mysql-group:0", NULL,
744  assert_ptr_equal(mysql_group_1, native_find_rsc(mysql_group_1, "mysql-group:1", NULL, 0));
745  assert_ptr_equal(mysql_group_1,
746  native_find_rsc(mysql_group_1, "mysql-group:1", NULL,
748 
749  // Fails because pcmk_rsc_match_current_node is required if a node is given
750  assert_null(native_find_rsc(mysql_group_0, "mysql-group:0", cluster02, 0));
751  assert_null(native_find_rsc(mysql_group_1, "mysql-group:1", cluster01, 0));
752 
753  /* Check that the resource is running on the node we expect. */
754  assert_ptr_equal(mysql_group_0,
755  native_find_rsc(mysql_group_0, "mysql-group:0", cluster02,
757  assert_null(native_find_rsc(mysql_group_0, "mysql-group:0", cluster01,
759  assert_ptr_equal(mysql_group_1,
760  native_find_rsc(mysql_group_1, "mysql-group:1", cluster01,
762  assert_null(native_find_rsc(mysql_group_1, "mysql-group:1", cluster02,
764 
765  /* Passes because NULL was passed for node and base name was given, with correct flags. */
766  assert_ptr_equal(mysql_group_0,
767  native_find_rsc(mysql_group_0, "mysql-group" , NULL,
769 
770  // Passes because pcmk_rsc_match_basename matches any base name
771  assert_ptr_equal(mysql_group_0,
772  native_find_rsc(mysql_group_0, "mysql-group" , NULL,
774  assert_ptr_equal(mysql_group_1,
775  native_find_rsc(mysql_group_1, "mysql-group" , NULL,
777 
778  // Passes because pcmk_rsc_match_anon_basename matches
779  assert_ptr_equal(mysql_group_0,
780  native_find_rsc(mysql_group_0, "mysql-group" , NULL,
782  assert_ptr_equal(mysql_group_1,
783  native_find_rsc(mysql_group_1, "mysql-group" , NULL,
785 
786  /* Check that the resource is running on the node we expect. */
787  assert_ptr_equal(mysql_group_0,
788  native_find_rsc(mysql_group_0, "mysql-group", cluster02,
791  assert_ptr_equal(mysql_group_0,
792  native_find_rsc(mysql_group_0, "mysql-group", cluster02,
795  assert_null(native_find_rsc(mysql_group_0, "mysql-group", cluster01,
798  assert_null(native_find_rsc(mysql_group_0, "mysql-group", cluster01,
801  assert_ptr_equal(mysql_group_1,
802  native_find_rsc(mysql_group_1, "mysql-group", cluster01,
805  assert_ptr_equal(mysql_group_1,
806  native_find_rsc(mysql_group_1, "mysql-group", cluster01,
809  assert_null(native_find_rsc(mysql_group_1, "mysql-group", cluster02,
812  assert_null(native_find_rsc(mysql_group_1, "mysql-group", cluster02,
815 
816  /* Fails because incorrect flags were given along with base name. */
817  assert_null(native_find_rsc(mysql_group_0, "mysql-group", NULL,
819  assert_null(native_find_rsc(mysql_group_1, "mysql-group", NULL,
821 
822  /* And then we check failure possibilities again, except passing mysql_clone_group
823  * instead of mysql_group_X as the first argument to native_find_rsc.
824  */
825 
826  // Fails because pcmk_rsc_match_current_node is required if a node is given
827  assert_null(native_find_rsc(mysql_clone_group, "mysql-group:0", cluster02, 0));
828  assert_null(native_find_rsc(mysql_clone_group, "mysql-group:1", cluster01, 0));
829 
830  /* Check that the resource is running on the node we expect. */
831  assert_ptr_equal(mysql_group_0,
832  native_find_rsc(mysql_clone_group, "mysql-group:0",
834  assert_ptr_equal(mysql_group_0,
835  native_find_rsc(mysql_clone_group, "mysql-group",
836  cluster02,
839  assert_ptr_equal(mysql_group_0,
840  native_find_rsc(mysql_clone_group, "mysql-group",
841  cluster02,
844  assert_ptr_equal(mysql_group_1,
845  native_find_rsc(mysql_clone_group, "mysql-group:1",
847  assert_ptr_equal(mysql_group_1,
848  native_find_rsc(mysql_clone_group, "mysql-group",
849  cluster01,
852  assert_ptr_equal(mysql_group_1,
853  native_find_rsc(mysql_clone_group, "mysql-group",
854  cluster01,
857 }
858 
859 static void
860 clone_group_member_rsc(void **state) {
861  pcmk_resource_t *mysql_proxy = NULL;
862 
863  /* Find the "mysql-proxy" resource, a member of "mysql-group". */
864  for (GList *iter = mysql_clone_group->priv->children;
865  iter != NULL; iter = iter->next) {
866 
867  pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
868 
869  if (strcmp(rsc->id, "mysql-group:0") == 0) {
870  for (GList *iter2 = rsc->priv->children;
871  iter2 != NULL; iter2 = iter2->next) {
872  pcmk_resource_t *child = (pcmk_resource_t *) iter2->data;
873 
874  if (strcmp(child->id, "mysql-proxy:0") == 0) {
875  mysql_proxy = child;
876  break;
877  }
878  }
879 
880  break;
881  }
882  }
883 
884  assert_non_null(mysql_proxy);
885 
886  /* Passes because NULL was passed for node, regardless of flags. */
887  assert_ptr_equal(mysql_proxy, native_find_rsc(mysql_proxy, "mysql-proxy:0", NULL, 0));
888  assert_ptr_equal(mysql_proxy,
889  native_find_rsc(mysql_proxy, "mysql-proxy:0", NULL,
891 
892  /* Passes because resource's parent is a clone. */
893  assert_ptr_equal(mysql_proxy,
894  native_find_rsc(mysql_proxy, "mysql-proxy:0", NULL,
896  assert_ptr_equal(mysql_proxy,
897  native_find_rsc(mysql_proxy, "mysql-proxy:0", cluster02,
900 
901  /* Fails because mysql-proxy:0 is not running on cluster01, even with the right flags. */
902  assert_null(native_find_rsc(mysql_proxy, "mysql-proxy:0", cluster01,
904 
905  // Fails because pcmk_rsc_match_current_node is required if a node is given
906  assert_null(native_find_rsc(mysql_proxy, "mysql-proxy:0", cluster02, 0));
907 
908  /* Passes because mysql-proxy:0 is running on cluster02. */
909  assert_ptr_equal(mysql_proxy,
910  native_find_rsc(mysql_proxy, "mysql-proxy:0", cluster02,
912 }
913 
914 /* TODO: Add tests for finding on assigned node (passing a node without
915  * pcmk_rsc_match_current_node, after scheduling, for a resource that is
916  * starting/stopping/moving.
917  */
918 PCMK__UNIT_TEST(setup, teardown,
919  cmocka_unit_test(bad_args),
920  cmocka_unit_test(primitive_rsc),
921  cmocka_unit_test(group_rsc),
922  cmocka_unit_test(inactive_group_rsc),
923  cmocka_unit_test(group_member_rsc),
924  cmocka_unit_test(inactive_group_member_rsc),
925  cmocka_unit_test(clone_rsc),
926  cmocka_unit_test(inactive_clone_rsc),
927  cmocka_unit_test(clone_instance_rsc),
928  cmocka_unit_test(renamed_rsc),
929  cmocka_unit_test(bundle_rsc),
930  cmocka_unit_test(bundle_replica_rsc),
931  cmocka_unit_test(clone_group_rsc),
932  cmocka_unit_test(clone_group_instance_rsc),
933  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:100
Also match anonymous clone instances by base name.
Definition: resources.h:37
pcmk_resource_t * dummy
const char * name
Definition: cib.c:26
pcmk_node_t * cluster01
Match only clones and their instances, by either clone or instance ID.
Definition: resources.h:40
void pe__foreach_bundle_replica(pcmk_resource_t *bundle, bool(*fn)(pcmk__bundle_replica_t *, void *), void *user_data)
Definition: bundle.c:207
void pcmk__xml_init(void)
Definition: xml.c:1430
pcmk_resource_t * ip
IP address resource for ipaddr.
pcmk__scheduler_private_t * priv
Definition: scheduler.h:99
pcmk_resource_t * inactive_clone
#define PCMK__UNIT_TEST(group_setup, group_teardown,...)
gboolean cluster_status(pcmk_scheduler_t *scheduler)
Definition: status.c:103
Scheduler API.
Also match clone instance ID from resource history.
Definition: resources.h:34
void pcmk__xml_cleanup(void)
Definition: xml.c:1456
pcmk_resource_t * promotable_0
pcmk__resource_private_t * priv
Definition: resources.h:61
Wrappers for and extensions to libxml2.
Match clone instances (even unique) by base name as well as exact ID.
Definition: resources.h:46
pcmk_resource_t * mysql_clone_group
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:102
void pe_free_working_set(pcmk_scheduler_t *scheduler)
Free scheduler data.
Definition: status.c:56
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:270
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:43
pcmk_node_t * cluster02
xmlNode * input
xmlNode * input
Definition: scheduler.h:81
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
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1