This source file includes following definitions.
- next_ip
- allocate_ip
- create_resource
- valid_network
- create_ip_resource
- container_agent_str
- create_container_resource
- disallow_node
- create_remote_resource
- create_replica_resources
- mount_add
- mount_free
- port_free
- replica_for_remote
- pe__bundle_needs_remote_name
- pe__add_bundle_remote_name
- pe__unpack_bundle
- replica_resource_active
- pe__bundle_active
- pe__find_bundle_replica
- print_rsc_in_list
- bundle_print_xml
- PCMK__OUTPUT_ARGS
- pe__bundle_replica_output_html
- PCMK__OUTPUT_ARGS
- pe__bundle_replica_output_text
- PCMK__OUTPUT_ARGS
- print_bundle_replica
- pe__print_bundle
- free_bundle_replica
- pe__free_bundle
- pe__bundle_resource_state
- pe_bundle_replicas
- pe__count_bundle
- pe__bundle_is_filtered
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <ctype.h>
13 #include <stdint.h>
14
15 #include <crm/pengine/rules.h>
16 #include <crm/pengine/status.h>
17 #include <crm/pengine/internal.h>
18 #include <crm/msg_xml.h>
19 #include <crm/common/output.h>
20 #include <crm/common/xml_internal.h>
21 #include <pe_status_private.h>
22
23 #define PE__VARIANT_BUNDLE 1
24 #include "./variant.h"
25
26 static char *
27 next_ip(const char *last_ip)
28 {
29 unsigned int oct1 = 0;
30 unsigned int oct2 = 0;
31 unsigned int oct3 = 0;
32 unsigned int oct4 = 0;
33 int rc = sscanf(last_ip, "%u.%u.%u.%u", &oct1, &oct2, &oct3, &oct4);
34
35 if (rc != 4) {
36
37 return NULL;
38
39 } else if (oct3 > 253) {
40 return NULL;
41
42 } else if (oct4 > 253) {
43 ++oct3;
44 oct4 = 1;
45
46 } else {
47 ++oct4;
48 }
49
50 return crm_strdup_printf("%u.%u.%u.%u", oct1, oct2, oct3, oct4);
51 }
52
53 static void
54 allocate_ip(pe__bundle_variant_data_t *data, pe__bundle_replica_t *replica,
55 GString *buffer)
56 {
57 if(data->ip_range_start == NULL) {
58 return;
59
60 } else if(data->ip_last) {
61 replica->ipaddr = next_ip(data->ip_last);
62
63 } else {
64 replica->ipaddr = strdup(data->ip_range_start);
65 }
66
67 data->ip_last = replica->ipaddr;
68 switch (data->agent_type) {
69 case PE__CONTAINER_AGENT_DOCKER:
70 case PE__CONTAINER_AGENT_PODMAN:
71 if (data->add_host) {
72 g_string_append_printf(buffer, " --add-host=%s-%d:%s",
73 data->prefix, replica->offset,
74 replica->ipaddr);
75 } else {
76 g_string_append_printf(buffer, " --hosts-entry=%s=%s-%d",
77 replica->ipaddr, data->prefix,
78 replica->offset);
79 }
80 break;
81
82 case PE__CONTAINER_AGENT_RKT:
83 g_string_append_printf(buffer, " --hosts-entry=%s=%s-%d",
84 replica->ipaddr, data->prefix,
85 replica->offset);
86 break;
87
88 default:
89 break;
90 }
91 }
92
93 static xmlNode *
94 create_resource(const char *name, const char *provider, const char *kind)
95 {
96 xmlNode *rsc = create_xml_node(NULL, XML_CIB_TAG_RESOURCE);
97
98 crm_xml_add(rsc, XML_ATTR_ID, name);
99 crm_xml_add(rsc, XML_AGENT_ATTR_CLASS, PCMK_RESOURCE_CLASS_OCF);
100 crm_xml_add(rsc, XML_AGENT_ATTR_PROVIDER, provider);
101 crm_xml_add(rsc, XML_ATTR_TYPE, kind);
102
103 return rsc;
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117
118 static bool
119 valid_network(pe__bundle_variant_data_t *data)
120 {
121 if(data->ip_range_start) {
122 return TRUE;
123 }
124 if(data->control_port) {
125 if(data->nreplicas_per_host > 1) {
126 pe_err("Specifying the 'control-port' for %s requires 'replicas-per-host=1'", data->prefix);
127 data->nreplicas_per_host = 1;
128
129 }
130 return TRUE;
131 }
132 return FALSE;
133 }
134
135 static int
136 create_ip_resource(pe_resource_t *parent, pe__bundle_variant_data_t *data,
137 pe__bundle_replica_t *replica)
138 {
139 if(data->ip_range_start) {
140 char *id = NULL;
141 xmlNode *xml_ip = NULL;
142 xmlNode *xml_obj = NULL;
143
144 id = crm_strdup_printf("%s-ip-%s", data->prefix, replica->ipaddr);
145 crm_xml_sanitize_id(id);
146 xml_ip = create_resource(id, "heartbeat", "IPaddr2");
147 free(id);
148
149 xml_obj = create_xml_node(xml_ip, XML_TAG_ATTR_SETS);
150 crm_xml_set_id(xml_obj, "%s-attributes-%d",
151 data->prefix, replica->offset);
152
153 crm_create_nvpair_xml(xml_obj, NULL, "ip", replica->ipaddr);
154 if(data->host_network) {
155 crm_create_nvpair_xml(xml_obj, NULL, "nic", data->host_network);
156 }
157
158 if(data->host_netmask) {
159 crm_create_nvpair_xml(xml_obj, NULL,
160 "cidr_netmask", data->host_netmask);
161
162 } else {
163 crm_create_nvpair_xml(xml_obj, NULL, "cidr_netmask", "32");
164 }
165
166 xml_obj = create_xml_node(xml_ip, "operations");
167 crm_create_op_xml(xml_obj, ID(xml_ip), "monitor", "60s", NULL);
168
169
170
171 if (pe__unpack_resource(xml_ip, &replica->ip, parent,
172 parent->cluster) != pcmk_rc_ok) {
173 return pcmk_rc_unpack_error;
174 }
175
176 parent->children = g_list_append(parent->children, replica->ip);
177 }
178 return pcmk_rc_ok;
179 }
180
181 static const char*
182 container_agent_str(enum pe__container_agent t)
183 {
184 switch (t) {
185 case PE__CONTAINER_AGENT_DOCKER: return PE__CONTAINER_AGENT_DOCKER_S;
186 case PE__CONTAINER_AGENT_RKT: return PE__CONTAINER_AGENT_RKT_S;
187 case PE__CONTAINER_AGENT_PODMAN: return PE__CONTAINER_AGENT_PODMAN_S;
188 default:
189 break;
190 }
191 return PE__CONTAINER_AGENT_UNKNOWN_S;
192 }
193
194 static int
195 create_container_resource(pe_resource_t *parent,
196 const pe__bundle_variant_data_t *data,
197 pe__bundle_replica_t *replica)
198 {
199 char *id = NULL;
200 xmlNode *xml_container = NULL;
201 xmlNode *xml_obj = NULL;
202
203
204 const char *hostname_opt = NULL;
205 const char *env_opt = NULL;
206 const char *agent_str = NULL;
207 int volid = 0;
208
209 GString *buffer = NULL;
210 GString *dbuffer = NULL;
211
212
213 switch (data->agent_type) {
214 case PE__CONTAINER_AGENT_DOCKER:
215 case PE__CONTAINER_AGENT_PODMAN:
216 hostname_opt = "-h ";
217 env_opt = "-e ";
218 break;
219 case PE__CONTAINER_AGENT_RKT:
220 hostname_opt = "--hostname=";
221 env_opt = "--environment=";
222 break;
223 default:
224 return pcmk_rc_unpack_error;
225 }
226 agent_str = container_agent_str(data->agent_type);
227
228 buffer = g_string_sized_new(4096);
229
230 id = crm_strdup_printf("%s-%s-%d", data->prefix, agent_str,
231 replica->offset);
232 crm_xml_sanitize_id(id);
233 xml_container = create_resource(id, "heartbeat", agent_str);
234 free(id);
235
236 xml_obj = create_xml_node(xml_container, XML_TAG_ATTR_SETS);
237 crm_xml_set_id(xml_obj, "%s-attributes-%d", data->prefix, replica->offset);
238
239 crm_create_nvpair_xml(xml_obj, NULL, "image", data->image);
240 crm_create_nvpair_xml(xml_obj, NULL, "allow_pull", XML_BOOLEAN_TRUE);
241 crm_create_nvpair_xml(xml_obj, NULL, "force_kill", XML_BOOLEAN_FALSE);
242 crm_create_nvpair_xml(xml_obj, NULL, "reuse", XML_BOOLEAN_FALSE);
243
244 if (data->agent_type == PE__CONTAINER_AGENT_DOCKER) {
245 g_string_append(buffer, " --restart=no");
246 }
247
248
249
250
251
252
253 if (data->ip_range_start != NULL) {
254 g_string_append_printf(buffer, " %s%s-%d", hostname_opt, data->prefix,
255 replica->offset);
256 }
257 pcmk__g_strcat(buffer, " ", env_opt, "PCMK_stderr=1", NULL);
258
259 if (data->container_network != NULL) {
260 pcmk__g_strcat(buffer, " --net=", data->container_network, NULL);
261 }
262
263 if (data->control_port != NULL) {
264 pcmk__g_strcat(buffer, " ", env_opt, "PCMK_remote_port=",
265 data->control_port, NULL);
266 } else {
267 g_string_append_printf(buffer, " %sPCMK_remote_port=%d", env_opt,
268 DEFAULT_REMOTE_PORT);
269 }
270
271 for (GList *iter = data->mounts; iter != NULL; iter = iter->next) {
272 pe__bundle_mount_t *mount = (pe__bundle_mount_t *) iter->data;
273 char *source = NULL;
274
275 if (pcmk_is_set(mount->flags, pe__bundle_mount_subdir)) {
276 source = crm_strdup_printf("%s/%s-%d", mount->source, data->prefix,
277 replica->offset);
278 pcmk__add_separated_word(&dbuffer, 1024, source, ",");
279 }
280
281 switch (data->agent_type) {
282 case PE__CONTAINER_AGENT_DOCKER:
283 case PE__CONTAINER_AGENT_PODMAN:
284 pcmk__g_strcat(buffer,
285 " -v ", pcmk__s(source, mount->source),
286 ":", mount->target, NULL);
287
288 if (mount->options != NULL) {
289 pcmk__g_strcat(buffer, ":", mount->options, NULL);
290 }
291 break;
292 case PE__CONTAINER_AGENT_RKT:
293 g_string_append_printf(buffer,
294 " --volume vol%d,kind=host,"
295 "source=%s%s%s "
296 "--mount volume=vol%d,target=%s",
297 volid, pcmk__s(source, mount->source),
298 (mount->options != NULL)? "," : "",
299 pcmk__s(mount->options, ""),
300 volid, mount->target);
301 volid++;
302 break;
303 default:
304 break;
305 }
306 free(source);
307 }
308
309 for (GList *iter = data->ports; iter != NULL; iter = iter->next) {
310 pe__bundle_port_t *port = (pe__bundle_port_t *) iter->data;
311
312 switch (data->agent_type) {
313 case PE__CONTAINER_AGENT_DOCKER:
314 case PE__CONTAINER_AGENT_PODMAN:
315 if (replica->ipaddr != NULL) {
316 pcmk__g_strcat(buffer,
317 " -p ", replica->ipaddr, ":", port->source,
318 ":", port->target, NULL);
319
320 } else if (!pcmk__str_eq(data->container_network, "host",
321 pcmk__str_none)) {
322
323 pcmk__g_strcat(buffer,
324 " -p ", port->source, ":", port->target,
325 NULL);
326 }
327 break;
328 case PE__CONTAINER_AGENT_RKT:
329 if (replica->ipaddr != NULL) {
330 pcmk__g_strcat(buffer,
331 " --port=", port->target,
332 ":", replica->ipaddr, ":", port->source,
333 NULL);
334 } else {
335 pcmk__g_strcat(buffer,
336 " --port=", port->target, ":", port->source,
337 NULL);
338 }
339 break;
340 default:
341 break;
342 }
343 }
344
345
346
347
348
349
350
351
352
353
354
355
356
357 if (data->launcher_options != NULL) {
358 pcmk__g_strcat(buffer, " ", data->launcher_options, NULL);
359 }
360
361 if (data->container_host_options != NULL) {
362 pcmk__g_strcat(buffer, " ", data->container_host_options, NULL);
363 }
364
365 crm_create_nvpair_xml(xml_obj, NULL, "run_opts",
366 (const char *) buffer->str);
367 g_string_free(buffer, TRUE);
368
369 crm_create_nvpair_xml(xml_obj, NULL, "mount_points",
370 (dbuffer != NULL)? (const char *) dbuffer->str : "");
371 if (dbuffer != NULL) {
372 g_string_free(dbuffer, TRUE);
373 }
374
375 if (replica->child != NULL) {
376 if (data->container_command != NULL) {
377 crm_create_nvpair_xml(xml_obj, NULL, "run_cmd",
378 data->container_command);
379 } else {
380 crm_create_nvpair_xml(xml_obj, NULL, "run_cmd",
381 SBIN_DIR "/pacemaker-remoted");
382 }
383
384
385
386
387
388
389 crm_create_nvpair_xml(xml_obj, NULL, "monitor_cmd", "/bin/true");
390 #if 0
391
392
393
394
395
396
397 } else if ((child != NULL) && data->untrusted) {
398 crm_create_nvpair_xml(xml_obj, NULL, "run_cmd",
399 CRM_DAEMON_DIR "/pacemaker-execd");
400 crm_create_nvpair_xml(xml_obj, NULL, "monitor_cmd",
401 CRM_DAEMON_DIR "/pacemaker/cts-exec-helper -c poke");
402 #endif
403 } else {
404 if (data->container_command != NULL) {
405 crm_create_nvpair_xml(xml_obj, NULL, "run_cmd",
406 data->container_command);
407 }
408
409
410
411
412
413
414 crm_create_nvpair_xml(xml_obj, NULL, "monitor_cmd", "/bin/true");
415 }
416
417 xml_obj = create_xml_node(xml_container, "operations");
418 crm_create_op_xml(xml_obj, ID(xml_container), "monitor", "60s", NULL);
419
420
421 if (pe__unpack_resource(xml_container, &replica->container, parent,
422 parent->cluster) != pcmk_rc_ok) {
423 return pcmk_rc_unpack_error;
424 }
425 parent->children = g_list_append(parent->children, replica->container);
426
427 return pcmk_rc_ok;
428 }
429
430
431
432
433
434
435
436 static void
437 disallow_node(pe_resource_t *rsc, const char *uname)
438 {
439 gpointer match = g_hash_table_lookup(rsc->allowed_nodes, uname);
440
441 if (match) {
442 ((pe_node_t *) match)->weight = -INFINITY;
443 ((pe_node_t *) match)->rsc_discover_mode = pe_discover_never;
444 }
445 if (rsc->children) {
446 g_list_foreach(rsc->children, (GFunc) disallow_node, (gpointer) uname);
447 }
448 }
449
450 static int
451 create_remote_resource(pe_resource_t *parent, pe__bundle_variant_data_t *data,
452 pe__bundle_replica_t *replica)
453 {
454 if (replica->child && valid_network(data)) {
455 GHashTableIter gIter;
456 pe_node_t *node = NULL;
457 xmlNode *xml_remote = NULL;
458 char *id = crm_strdup_printf("%s-%d", data->prefix, replica->offset);
459 char *port_s = NULL;
460 const char *uname = NULL;
461 const char *connect_name = NULL;
462
463 if (pe_find_resource(parent->cluster->resources, id) != NULL) {
464 free(id);
465
466 id = crm_strdup_printf("pcmk-internal-%s-remote-%d",
467 replica->child->id, replica->offset);
468
469 CRM_ASSERT(pe_find_resource(parent->cluster->resources,
470 id) == NULL);
471 }
472
473
474
475
476
477 connect_name = (replica->ipaddr? replica->ipaddr : "#uname");
478
479 if (data->control_port == NULL) {
480 port_s = pcmk__itoa(DEFAULT_REMOTE_PORT);
481 }
482
483
484
485
486
487
488 xml_remote = pe_create_remote_xml(NULL, id, replica->container->id,
489 NULL, NULL, NULL,
490 connect_name, (data->control_port?
491 data->control_port : port_s));
492 free(port_s);
493
494
495
496
497
498 free(id);
499 id = NULL;
500 uname = ID(xml_remote);
501
502
503
504
505
506 node = pe_find_node(parent->cluster->nodes, uname);
507 if (node == NULL) {
508 node = pe_create_node(uname, uname, "remote", "-INFINITY",
509 parent->cluster);
510 } else {
511 node->weight = -INFINITY;
512 }
513 node->rsc_discover_mode = pe_discover_never;
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532 g_list_foreach(parent->cluster->resources, (GFunc) disallow_node,
533 (gpointer) uname);
534
535 replica->node = pe__copy_node(node);
536 replica->node->weight = 500;
537 replica->node->rsc_discover_mode = pe_discover_exclusive;
538
539
540 if (replica->child->allowed_nodes != NULL) {
541 g_hash_table_destroy(replica->child->allowed_nodes);
542 }
543 replica->child->allowed_nodes = pcmk__strkey_table(NULL, free);
544 g_hash_table_insert(replica->child->allowed_nodes,
545 (gpointer) replica->node->details->id,
546 pe__copy_node(replica->node));
547
548 {
549 pe_node_t *copy = pe__copy_node(replica->node);
550 copy->weight = -INFINITY;
551 g_hash_table_insert(replica->child->parent->allowed_nodes,
552 (gpointer) replica->node->details->id, copy);
553 }
554 if (pe__unpack_resource(xml_remote, &replica->remote, parent,
555 parent->cluster) != pcmk_rc_ok) {
556 return pcmk_rc_unpack_error;
557 }
558
559 g_hash_table_iter_init(&gIter, replica->remote->allowed_nodes);
560 while (g_hash_table_iter_next(&gIter, NULL, (void **)&node)) {
561 if (pe__is_guest_or_remote_node(node)) {
562
563 node->weight = -INFINITY;
564 }
565 }
566
567 replica->node->details->remote_rsc = replica->remote;
568
569
570 replica->remote->container = replica->container;
571
572
573
574
575 g_hash_table_insert(replica->node->details->attrs,
576 strdup(CRM_ATTR_KIND), strdup("container"));
577
578
579
580
581
582
583
584
585
586
587 parent->children = g_list_append(parent->children, replica->remote);
588 }
589 return pcmk_rc_ok;
590 }
591
592 static int
593 create_replica_resources(pe_resource_t *parent, pe__bundle_variant_data_t *data,
594 pe__bundle_replica_t *replica)
595 {
596 int rc = pcmk_rc_ok;
597
598 rc = create_container_resource(parent, data, replica);
599 if (rc != pcmk_rc_ok) {
600 return rc;
601 }
602
603 rc = create_ip_resource(parent, data, replica);
604 if (rc != pcmk_rc_ok) {
605 return rc;
606 }
607
608 rc = create_remote_resource(parent, data, replica);
609 if (rc != pcmk_rc_ok) {
610 return rc;
611 }
612
613 if ((replica->child != NULL) && (replica->ipaddr != NULL)) {
614 add_hash_param(replica->child->meta, "external-ip", replica->ipaddr);
615 }
616
617 if (replica->remote != NULL) {
618
619
620
621
622
623
624
625
626 pe__set_resource_flags(replica->remote, pe_rsc_allow_remote_remotes);
627 }
628 return rc;
629 }
630
631 static void
632 mount_add(pe__bundle_variant_data_t *bundle_data, const char *source,
633 const char *target, const char *options, uint32_t flags)
634 {
635 pe__bundle_mount_t *mount = calloc(1, sizeof(pe__bundle_mount_t));
636
637 CRM_ASSERT(mount != NULL);
638 mount->source = strdup(source);
639 mount->target = strdup(target);
640 pcmk__str_update(&mount->options, options);
641 mount->flags = flags;
642 bundle_data->mounts = g_list_append(bundle_data->mounts, mount);
643 }
644
645 static void
646 mount_free(pe__bundle_mount_t *mount)
647 {
648 free(mount->source);
649 free(mount->target);
650 free(mount->options);
651 free(mount);
652 }
653
654 static void
655 port_free(pe__bundle_port_t *port)
656 {
657 free(port->source);
658 free(port->target);
659 free(port);
660 }
661
662 static pe__bundle_replica_t *
663 replica_for_remote(pe_resource_t *remote)
664 {
665 pe_resource_t *top = remote;
666 pe__bundle_variant_data_t *bundle_data = NULL;
667
668 if (top == NULL) {
669 return NULL;
670 }
671
672 while (top->parent != NULL) {
673 top = top->parent;
674 }
675
676 get_bundle_variant_data(bundle_data, top);
677 for (GList *gIter = bundle_data->replicas; gIter != NULL;
678 gIter = gIter->next) {
679 pe__bundle_replica_t *replica = gIter->data;
680
681 if (replica->remote == remote) {
682 return replica;
683 }
684 }
685 CRM_LOG_ASSERT(FALSE);
686 return NULL;
687 }
688
689 bool
690 pe__bundle_needs_remote_name(pe_resource_t *rsc, pe_working_set_t *data_set)
691 {
692 const char *value;
693 GHashTable *params = NULL;
694
695 if (rsc == NULL) {
696 return false;
697 }
698
699
700 params = pe_rsc_params(rsc, NULL, data_set);
701 value = g_hash_table_lookup(params, XML_RSC_ATTR_REMOTE_RA_ADDR);
702
703 return pcmk__str_eq(value, "#uname", pcmk__str_casei)
704 && xml_contains_remote_node(rsc->xml);
705 }
706
707 const char *
708 pe__add_bundle_remote_name(pe_resource_t *rsc, pe_working_set_t *data_set,
709 xmlNode *xml, const char *field)
710 {
711
712
713 pe_node_t *node = NULL;
714 pe__bundle_replica_t *replica = NULL;
715
716 if (!pe__bundle_needs_remote_name(rsc, data_set)) {
717 return NULL;
718 }
719
720 replica = replica_for_remote(rsc);
721 if (replica == NULL) {
722 return NULL;
723 }
724
725 node = replica->container->allocated_to;
726 if (node == NULL) {
727
728
729
730 node = pe__current_node(replica->container);
731 }
732
733 if(node == NULL) {
734 crm_trace("Cannot determine address for bundle connection %s", rsc->id);
735 return NULL;
736 }
737
738 crm_trace("Setting address for bundle connection %s to bundle host %s",
739 rsc->id, pe__node_name(node));
740 if(xml != NULL && field != NULL) {
741 crm_xml_add(xml, field, node->details->uname);
742 }
743
744 return node->details->uname;
745 }
746
747 #define pe__set_bundle_mount_flags(mount_xml, flags, flags_to_set) do { \
748 flags = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \
749 "Bundle mount", ID(mount_xml), flags, \
750 (flags_to_set), #flags_to_set); \
751 } while (0)
752
753 gboolean
754 pe__unpack_bundle(pe_resource_t *rsc, pe_working_set_t *data_set)
755 {
756 const char *value = NULL;
757 xmlNode *xml_obj = NULL;
758 xmlNode *xml_resource = NULL;
759 pe__bundle_variant_data_t *bundle_data = NULL;
760 bool need_log_mount = TRUE;
761
762 CRM_ASSERT(rsc != NULL);
763 pe_rsc_trace(rsc, "Processing resource %s...", rsc->id);
764
765 bundle_data = calloc(1, sizeof(pe__bundle_variant_data_t));
766 rsc->variant_opaque = bundle_data;
767 bundle_data->prefix = strdup(rsc->id);
768
769 xml_obj = first_named_child(rsc->xml, PE__CONTAINER_AGENT_DOCKER_S);
770 if (xml_obj != NULL) {
771 bundle_data->agent_type = PE__CONTAINER_AGENT_DOCKER;
772 } else {
773 xml_obj = first_named_child(rsc->xml, PE__CONTAINER_AGENT_RKT_S);
774 if (xml_obj != NULL) {
775 bundle_data->agent_type = PE__CONTAINER_AGENT_RKT;
776 } else {
777 xml_obj = first_named_child(rsc->xml, PE__CONTAINER_AGENT_PODMAN_S);
778 if (xml_obj != NULL) {
779 bundle_data->agent_type = PE__CONTAINER_AGENT_PODMAN;
780 } else {
781 return FALSE;
782 }
783 }
784 }
785
786
787 value = crm_element_value(xml_obj, XML_RSC_ATTR_PROMOTED_MAX);
788 if (value == NULL) {
789
790 value = crm_element_value(xml_obj, "masters");
791 }
792 pcmk__scan_min_int(value, &bundle_data->promoted_max, 0);
793
794
795 value = crm_element_value(xml_obj, "replicas");
796 if ((value == NULL) && (bundle_data->promoted_max > 0)) {
797 bundle_data->nreplicas = bundle_data->promoted_max;
798 } else {
799 pcmk__scan_min_int(value, &bundle_data->nreplicas, 1);
800 }
801
802
803
804
805
806
807 value = crm_element_value(xml_obj, "replicas-per-host");
808 pcmk__scan_min_int(value, &bundle_data->nreplicas_per_host, 1);
809 if (bundle_data->nreplicas_per_host == 1) {
810 pe__clear_resource_flags(rsc, pe_rsc_unique);
811 }
812
813 bundle_data->container_command = crm_element_value_copy(xml_obj, "run-command");
814 bundle_data->launcher_options = crm_element_value_copy(xml_obj, "options");
815 bundle_data->image = crm_element_value_copy(xml_obj, "image");
816 bundle_data->container_network = crm_element_value_copy(xml_obj, "network");
817
818 xml_obj = first_named_child(rsc->xml, "network");
819 if(xml_obj) {
820
821 bundle_data->ip_range_start = crm_element_value_copy(xml_obj, "ip-range-start");
822 bundle_data->host_netmask = crm_element_value_copy(xml_obj, "host-netmask");
823 bundle_data->host_network = crm_element_value_copy(xml_obj, "host-interface");
824 bundle_data->control_port = crm_element_value_copy(xml_obj, "control-port");
825 value = crm_element_value(xml_obj, "add-host");
826 if (crm_str_to_boolean(value, &bundle_data->add_host) != 1) {
827 bundle_data->add_host = TRUE;
828 }
829
830 for (xmlNode *xml_child = pcmk__xe_first_child(xml_obj); xml_child != NULL;
831 xml_child = pcmk__xe_next(xml_child)) {
832
833 pe__bundle_port_t *port = calloc(1, sizeof(pe__bundle_port_t));
834 port->source = crm_element_value_copy(xml_child, "port");
835
836 if(port->source == NULL) {
837 port->source = crm_element_value_copy(xml_child, "range");
838 } else {
839 port->target = crm_element_value_copy(xml_child, "internal-port");
840 }
841
842 if(port->source != NULL && strlen(port->source) > 0) {
843 if(port->target == NULL) {
844 port->target = strdup(port->source);
845 }
846 bundle_data->ports = g_list_append(bundle_data->ports, port);
847
848 } else {
849 pe_err("Invalid port directive %s", ID(xml_child));
850 port_free(port);
851 }
852 }
853 }
854
855 xml_obj = first_named_child(rsc->xml, "storage");
856 for (xmlNode *xml_child = pcmk__xe_first_child(xml_obj); xml_child != NULL;
857 xml_child = pcmk__xe_next(xml_child)) {
858
859 const char *source = crm_element_value(xml_child, "source-dir");
860 const char *target = crm_element_value(xml_child, "target-dir");
861 const char *options = crm_element_value(xml_child, "options");
862 int flags = pe__bundle_mount_none;
863
864 if (source == NULL) {
865 source = crm_element_value(xml_child, "source-dir-root");
866 pe__set_bundle_mount_flags(xml_child, flags,
867 pe__bundle_mount_subdir);
868 }
869
870 if (source && target) {
871 mount_add(bundle_data, source, target, options, flags);
872 if (strcmp(target, "/var/log") == 0) {
873 need_log_mount = FALSE;
874 }
875 } else {
876 pe_err("Invalid mount directive %s", ID(xml_child));
877 }
878 }
879
880 xml_obj = first_named_child(rsc->xml, "primitive");
881 if (xml_obj && valid_network(bundle_data)) {
882 char *value = NULL;
883 xmlNode *xml_set = NULL;
884
885 xml_resource = create_xml_node(NULL, XML_CIB_TAG_INCARNATION);
886
887
888
889
890
891 crm_xml_set_id(xml_resource, "%s-%s", bundle_data->prefix,
892 (bundle_data->promoted_max? "master"
893 : (const char *)xml_resource->name));
894
895 xml_set = create_xml_node(xml_resource, XML_TAG_META_SETS);
896 crm_xml_set_id(xml_set, "%s-%s-meta", bundle_data->prefix, xml_resource->name);
897
898 crm_create_nvpair_xml(xml_set, NULL,
899 XML_RSC_ATTR_ORDERED, XML_BOOLEAN_TRUE);
900
901 value = pcmk__itoa(bundle_data->nreplicas);
902 crm_create_nvpair_xml(xml_set, NULL,
903 XML_RSC_ATTR_INCARNATION_MAX, value);
904 free(value);
905
906 value = pcmk__itoa(bundle_data->nreplicas_per_host);
907 crm_create_nvpair_xml(xml_set, NULL,
908 XML_RSC_ATTR_INCARNATION_NODEMAX, value);
909 free(value);
910
911 crm_create_nvpair_xml(xml_set, NULL, XML_RSC_ATTR_UNIQUE,
912 pcmk__btoa(bundle_data->nreplicas_per_host > 1));
913
914 if (bundle_data->promoted_max) {
915 crm_create_nvpair_xml(xml_set, NULL,
916 XML_RSC_ATTR_PROMOTABLE, XML_BOOLEAN_TRUE);
917
918 value = pcmk__itoa(bundle_data->promoted_max);
919 crm_create_nvpair_xml(xml_set, NULL,
920 XML_RSC_ATTR_PROMOTED_MAX, value);
921 free(value);
922 }
923
924
925 add_node_copy(xml_resource, xml_obj);
926
927 } else if(xml_obj) {
928 pe_err("Cannot control %s inside %s without either ip-range-start or control-port",
929 rsc->id, ID(xml_obj));
930 return FALSE;
931 }
932
933 if(xml_resource) {
934 int lpc = 0;
935 GList *childIter = NULL;
936 pe__bundle_port_t *port = NULL;
937 GString *buffer = NULL;
938
939 if (pe__unpack_resource(xml_resource, &(bundle_data->child), rsc,
940 data_set) != pcmk_rc_ok) {
941 return FALSE;
942 }
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965 mount_add(bundle_data, DEFAULT_REMOTE_KEY_LOCATION,
966 DEFAULT_REMOTE_KEY_LOCATION, NULL, pe__bundle_mount_none);
967
968 if (need_log_mount) {
969 mount_add(bundle_data, CRM_BUNDLE_DIR, "/var/log", NULL,
970 pe__bundle_mount_subdir);
971 }
972
973 port = calloc(1, sizeof(pe__bundle_port_t));
974 if(bundle_data->control_port) {
975 port->source = strdup(bundle_data->control_port);
976 } else {
977
978
979
980
981
982
983
984
985 port->source = pcmk__itoa(DEFAULT_REMOTE_PORT);
986 }
987 port->target = strdup(port->source);
988 bundle_data->ports = g_list_append(bundle_data->ports, port);
989
990 buffer = g_string_sized_new(1024);
991 for (childIter = bundle_data->child->children; childIter != NULL;
992 childIter = childIter->next) {
993
994 pe__bundle_replica_t *replica = calloc(1, sizeof(pe__bundle_replica_t));
995
996 replica->child = childIter->data;
997 replica->child->exclusive_discover = TRUE;
998 replica->offset = lpc++;
999
1000
1001 if (pcmk_is_set(replica->child->flags, pe_rsc_notify)) {
1002 pe__set_resource_flags(bundle_data->child, pe_rsc_notify);
1003 }
1004
1005 allocate_ip(bundle_data, replica, buffer);
1006 bundle_data->replicas = g_list_append(bundle_data->replicas,
1007 replica);
1008 bundle_data->attribute_target = g_hash_table_lookup(replica->child->meta,
1009 XML_RSC_ATTR_TARGET);
1010 }
1011 bundle_data->container_host_options = g_string_free(buffer, FALSE);
1012
1013 if (bundle_data->attribute_target) {
1014 g_hash_table_replace(rsc->meta, strdup(XML_RSC_ATTR_TARGET),
1015 strdup(bundle_data->attribute_target));
1016 g_hash_table_replace(bundle_data->child->meta,
1017 strdup(XML_RSC_ATTR_TARGET),
1018 strdup(bundle_data->attribute_target));
1019 }
1020
1021 } else {
1022
1023 GString *buffer = g_string_sized_new(1024);
1024
1025 for (int lpc = 0; lpc < bundle_data->nreplicas; lpc++) {
1026 pe__bundle_replica_t *replica = calloc(1, sizeof(pe__bundle_replica_t));
1027
1028 replica->offset = lpc;
1029 allocate_ip(bundle_data, replica, buffer);
1030 bundle_data->replicas = g_list_append(bundle_data->replicas,
1031 replica);
1032 }
1033 bundle_data->container_host_options = g_string_free(buffer, FALSE);
1034 }
1035
1036 for (GList *gIter = bundle_data->replicas; gIter != NULL;
1037 gIter = gIter->next) {
1038 pe__bundle_replica_t *replica = gIter->data;
1039
1040 if (create_replica_resources(rsc, bundle_data, replica) != pcmk_rc_ok) {
1041 pe_err("Failed unpacking resource %s", rsc->id);
1042 rsc->fns->free(rsc);
1043 return FALSE;
1044 }
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062 if (replica->child != NULL) {
1063 GHashTable *empty = replica->container->utilization;
1064
1065 replica->container->utilization = replica->child->utilization;
1066 replica->child->utilization = empty;
1067 }
1068 }
1069
1070 if (bundle_data->child) {
1071 rsc->children = g_list_append(rsc->children, bundle_data->child);
1072 }
1073 return TRUE;
1074 }
1075
1076 static int
1077 replica_resource_active(pe_resource_t *rsc, gboolean all)
1078 {
1079 if (rsc) {
1080 gboolean child_active = rsc->fns->active(rsc, all);
1081
1082 if (child_active && !all) {
1083 return TRUE;
1084 } else if (!child_active && all) {
1085 return FALSE;
1086 }
1087 }
1088 return -1;
1089 }
1090
1091 gboolean
1092 pe__bundle_active(pe_resource_t *rsc, gboolean all)
1093 {
1094 pe__bundle_variant_data_t *bundle_data = NULL;
1095 GList *iter = NULL;
1096
1097 get_bundle_variant_data(bundle_data, rsc);
1098 for (iter = bundle_data->replicas; iter != NULL; iter = iter->next) {
1099 pe__bundle_replica_t *replica = iter->data;
1100 int rsc_active;
1101
1102 rsc_active = replica_resource_active(replica->ip, all);
1103 if (rsc_active >= 0) {
1104 return (gboolean) rsc_active;
1105 }
1106
1107 rsc_active = replica_resource_active(replica->child, all);
1108 if (rsc_active >= 0) {
1109 return (gboolean) rsc_active;
1110 }
1111
1112 rsc_active = replica_resource_active(replica->container, all);
1113 if (rsc_active >= 0) {
1114 return (gboolean) rsc_active;
1115 }
1116
1117 rsc_active = replica_resource_active(replica->remote, all);
1118 if (rsc_active >= 0) {
1119 return (gboolean) rsc_active;
1120 }
1121 }
1122
1123
1124
1125
1126
1127 return all;
1128 }
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139 pe_resource_t *
1140 pe__find_bundle_replica(const pe_resource_t *bundle, const pe_node_t *node)
1141 {
1142 pe__bundle_variant_data_t *bundle_data = NULL;
1143 CRM_ASSERT(bundle && node);
1144
1145 get_bundle_variant_data(bundle_data, bundle);
1146 for (GList *gIter = bundle_data->replicas; gIter != NULL;
1147 gIter = gIter->next) {
1148 pe__bundle_replica_t *replica = gIter->data;
1149
1150 CRM_ASSERT(replica && replica->node);
1151 if (replica->node->details == node->details) {
1152 return replica->child;
1153 }
1154 }
1155 return NULL;
1156 }
1157
1158
1159
1160
1161
1162 static void
1163 print_rsc_in_list(pe_resource_t *rsc, const char *pre_text, long options,
1164 void *print_data)
1165 {
1166 if (rsc != NULL) {
1167 if (options & pe_print_html) {
1168 status_print("<li>");
1169 }
1170 rsc->fns->print(rsc, pre_text, options, print_data);
1171 if (options & pe_print_html) {
1172 status_print("</li>\n");
1173 }
1174 }
1175 }
1176
1177
1178
1179
1180
1181 static void
1182 bundle_print_xml(pe_resource_t *rsc, const char *pre_text, long options,
1183 void *print_data)
1184 {
1185 pe__bundle_variant_data_t *bundle_data = NULL;
1186 char *child_text = NULL;
1187 CRM_CHECK(rsc != NULL, return);
1188
1189 if (pre_text == NULL) {
1190 pre_text = "";
1191 }
1192 child_text = crm_strdup_printf("%s ", pre_text);
1193
1194 get_bundle_variant_data(bundle_data, rsc);
1195
1196 status_print("%s<bundle ", pre_text);
1197 status_print("id=\"%s\" ", rsc->id);
1198 status_print("type=\"%s\" ", container_agent_str(bundle_data->agent_type));
1199 status_print("image=\"%s\" ", bundle_data->image);
1200 status_print("unique=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_unique));
1201 status_print("managed=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_managed));
1202 status_print("failed=\"%s\" ", pe__rsc_bool_str(rsc, pe_rsc_failed));
1203 status_print(">\n");
1204
1205 for (GList *gIter = bundle_data->replicas; gIter != NULL;
1206 gIter = gIter->next) {
1207 pe__bundle_replica_t *replica = gIter->data;
1208
1209 CRM_ASSERT(replica);
1210 status_print("%s <replica id=\"%d\">\n", pre_text, replica->offset);
1211 print_rsc_in_list(replica->ip, child_text, options, print_data);
1212 print_rsc_in_list(replica->child, child_text, options, print_data);
1213 print_rsc_in_list(replica->container, child_text, options, print_data);
1214 print_rsc_in_list(replica->remote, child_text, options, print_data);
1215 status_print("%s </replica>\n", pre_text);
1216 }
1217 status_print("%s</bundle>\n", pre_text);
1218 free(child_text);
1219 }
1220
1221 PCMK__OUTPUT_ARGS("bundle", "uint32_t", "pe_resource_t *", "GList *", "GList *")
1222 int
1223 pe__bundle_xml(pcmk__output_t *out, va_list args)
1224 {
1225 uint32_t show_opts = va_arg(args, uint32_t);
1226 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1227 GList *only_node = va_arg(args, GList *);
1228 GList *only_rsc = va_arg(args, GList *);
1229
1230 pe__bundle_variant_data_t *bundle_data = NULL;
1231 int rc = pcmk_rc_no_output;
1232 gboolean printed_header = FALSE;
1233 gboolean print_everything = TRUE;
1234
1235 CRM_ASSERT(rsc != NULL);
1236
1237 get_bundle_variant_data(bundle_data, rsc);
1238
1239 if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1240 return rc;
1241 }
1242
1243 print_everything = pcmk__str_in_list(rsc->id, only_rsc, pcmk__str_star_matches);
1244
1245 for (GList *gIter = bundle_data->replicas; gIter != NULL;
1246 gIter = gIter->next) {
1247 pe__bundle_replica_t *replica = gIter->data;
1248 char *id = NULL;
1249 gboolean print_ip, print_child, print_ctnr, print_remote;
1250
1251 CRM_ASSERT(replica);
1252
1253 if (pcmk__rsc_filtered_by_node(replica->container, only_node)) {
1254 continue;
1255 }
1256
1257 print_ip = replica->ip != NULL &&
1258 !replica->ip->fns->is_filtered(replica->ip, only_rsc, print_everything);
1259 print_child = replica->child != NULL &&
1260 !replica->child->fns->is_filtered(replica->child, only_rsc, print_everything);
1261 print_ctnr = !replica->container->fns->is_filtered(replica->container, only_rsc, print_everything);
1262 print_remote = replica->remote != NULL &&
1263 !replica->remote->fns->is_filtered(replica->remote, only_rsc, print_everything);
1264
1265 if (!print_everything && !print_ip && !print_child && !print_ctnr && !print_remote) {
1266 continue;
1267 }
1268
1269 if (!printed_header) {
1270 printed_header = TRUE;
1271
1272 rc = pe__name_and_nvpairs_xml(out, true, "bundle", 6,
1273 "id", rsc->id,
1274 "type", container_agent_str(bundle_data->agent_type),
1275 "image", bundle_data->image,
1276 "unique", pe__rsc_bool_str(rsc, pe_rsc_unique),
1277 "managed", pe__rsc_bool_str(rsc, pe_rsc_managed),
1278 "failed", pe__rsc_bool_str(rsc, pe_rsc_failed));
1279 CRM_ASSERT(rc == pcmk_rc_ok);
1280 }
1281
1282 id = pcmk__itoa(replica->offset);
1283 rc = pe__name_and_nvpairs_xml(out, true, "replica", 1, "id", id);
1284 free(id);
1285 CRM_ASSERT(rc == pcmk_rc_ok);
1286
1287 if (print_ip) {
1288 out->message(out, crm_map_element_name(replica->ip->xml), show_opts,
1289 replica->ip, only_node, only_rsc);
1290 }
1291
1292 if (print_child) {
1293 out->message(out, crm_map_element_name(replica->child->xml), show_opts,
1294 replica->child, only_node, only_rsc);
1295 }
1296
1297 if (print_ctnr) {
1298 out->message(out, crm_map_element_name(replica->container->xml), show_opts,
1299 replica->container, only_node, only_rsc);
1300 }
1301
1302 if (print_remote) {
1303 out->message(out, crm_map_element_name(replica->remote->xml), show_opts,
1304 replica->remote, only_node, only_rsc);
1305 }
1306
1307 pcmk__output_xml_pop_parent(out);
1308 }
1309
1310 if (printed_header) {
1311 pcmk__output_xml_pop_parent(out);
1312 }
1313
1314 return rc;
1315 }
1316
1317 static void
1318 pe__bundle_replica_output_html(pcmk__output_t *out, pe__bundle_replica_t *replica,
1319 pe_node_t *node, uint32_t show_opts)
1320 {
1321 pe_resource_t *rsc = replica->child;
1322
1323 int offset = 0;
1324 char buffer[LINE_MAX];
1325
1326 if(rsc == NULL) {
1327 rsc = replica->container;
1328 }
1329
1330 if (replica->remote) {
1331 offset += snprintf(buffer + offset, LINE_MAX - offset, "%s",
1332 rsc_printable_id(replica->remote));
1333 } else {
1334 offset += snprintf(buffer + offset, LINE_MAX - offset, "%s",
1335 rsc_printable_id(replica->container));
1336 }
1337 if (replica->ipaddr) {
1338 offset += snprintf(buffer + offset, LINE_MAX - offset, " (%s)",
1339 replica->ipaddr);
1340 }
1341
1342 pe__common_output_html(out, rsc, buffer, node, show_opts);
1343 }
1344
1345 PCMK__OUTPUT_ARGS("bundle", "uint32_t", "pe_resource_t *", "GList *", "GList *")
1346 int
1347 pe__bundle_html(pcmk__output_t *out, va_list args)
1348 {
1349 uint32_t show_opts = va_arg(args, uint32_t);
1350 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1351 GList *only_node = va_arg(args, GList *);
1352 GList *only_rsc = va_arg(args, GList *);
1353
1354 pe__bundle_variant_data_t *bundle_data = NULL;
1355 int rc = pcmk_rc_no_output;
1356 gboolean print_everything = TRUE;
1357
1358 CRM_ASSERT(rsc != NULL);
1359
1360 get_bundle_variant_data(bundle_data, rsc);
1361
1362 if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1363 return rc;
1364 }
1365
1366 print_everything = pcmk__str_in_list(rsc->id, only_rsc, pcmk__str_star_matches);
1367
1368 for (GList *gIter = bundle_data->replicas; gIter != NULL;
1369 gIter = gIter->next) {
1370 pe__bundle_replica_t *replica = gIter->data;
1371 gboolean print_ip, print_child, print_ctnr, print_remote;
1372
1373 CRM_ASSERT(replica);
1374
1375 if (pcmk__rsc_filtered_by_node(replica->container, only_node)) {
1376 continue;
1377 }
1378
1379 print_ip = replica->ip != NULL &&
1380 !replica->ip->fns->is_filtered(replica->ip, only_rsc, print_everything);
1381 print_child = replica->child != NULL &&
1382 !replica->child->fns->is_filtered(replica->child, only_rsc, print_everything);
1383 print_ctnr = !replica->container->fns->is_filtered(replica->container, only_rsc, print_everything);
1384 print_remote = replica->remote != NULL &&
1385 !replica->remote->fns->is_filtered(replica->remote, only_rsc, print_everything);
1386
1387 if (pcmk_is_set(show_opts, pcmk_show_implicit_rscs) ||
1388 (print_everything == FALSE && (print_ip || print_child || print_ctnr || print_remote))) {
1389
1390
1391
1392 uint32_t new_show_opts = show_opts | pcmk_show_implicit_rscs;
1393
1394 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Container bundle%s: %s [%s]%s%s",
1395 (bundle_data->nreplicas > 1)? " set" : "",
1396 rsc->id, bundle_data->image,
1397 pcmk_is_set(rsc->flags, pe_rsc_unique) ? " (unique)" : "",
1398 pcmk_is_set(rsc->flags, pe_rsc_managed) ? "" : " (unmanaged)");
1399
1400 if (pcmk__list_of_multiple(bundle_data->replicas)) {
1401 out->begin_list(out, NULL, NULL, "Replica[%d]", replica->offset);
1402 }
1403
1404 if (print_ip) {
1405 out->message(out, crm_map_element_name(replica->ip->xml),
1406 new_show_opts, replica->ip, only_node, only_rsc);
1407 }
1408
1409 if (print_child) {
1410 out->message(out, crm_map_element_name(replica->child->xml),
1411 new_show_opts, replica->child, only_node, only_rsc);
1412 }
1413
1414 if (print_ctnr) {
1415 out->message(out, crm_map_element_name(replica->container->xml),
1416 new_show_opts, replica->container, only_node, only_rsc);
1417 }
1418
1419 if (print_remote) {
1420 out->message(out, crm_map_element_name(replica->remote->xml),
1421 new_show_opts, replica->remote, only_node, only_rsc);
1422 }
1423
1424 if (pcmk__list_of_multiple(bundle_data->replicas)) {
1425 out->end_list(out);
1426 }
1427 } else if (print_everything == FALSE && !(print_ip || print_child || print_ctnr || print_remote)) {
1428 continue;
1429 } else {
1430 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Container bundle%s: %s [%s]%s%s",
1431 (bundle_data->nreplicas > 1)? " set" : "",
1432 rsc->id, bundle_data->image,
1433 pcmk_is_set(rsc->flags, pe_rsc_unique) ? " (unique)" : "",
1434 pcmk_is_set(rsc->flags, pe_rsc_managed) ? "" : " (unmanaged)");
1435
1436 pe__bundle_replica_output_html(out, replica, pe__current_node(replica->container),
1437 show_opts);
1438 }
1439 }
1440
1441 PCMK__OUTPUT_LIST_FOOTER(out, rc);
1442 return rc;
1443 }
1444
1445 static void
1446 pe__bundle_replica_output_text(pcmk__output_t *out, pe__bundle_replica_t *replica,
1447 pe_node_t *node, uint32_t show_opts)
1448 {
1449 pe_resource_t *rsc = replica->child;
1450
1451 int offset = 0;
1452 char buffer[LINE_MAX];
1453
1454 if(rsc == NULL) {
1455 rsc = replica->container;
1456 }
1457
1458 if (replica->remote) {
1459 offset += snprintf(buffer + offset, LINE_MAX - offset, "%s",
1460 rsc_printable_id(replica->remote));
1461 } else {
1462 offset += snprintf(buffer + offset, LINE_MAX - offset, "%s",
1463 rsc_printable_id(replica->container));
1464 }
1465 if (replica->ipaddr) {
1466 offset += snprintf(buffer + offset, LINE_MAX - offset, " (%s)",
1467 replica->ipaddr);
1468 }
1469
1470 pe__common_output_text(out, rsc, buffer, node, show_opts);
1471 }
1472
1473 PCMK__OUTPUT_ARGS("bundle", "uint32_t", "pe_resource_t *", "GList *", "GList *")
1474 int
1475 pe__bundle_text(pcmk__output_t *out, va_list args)
1476 {
1477 uint32_t show_opts = va_arg(args, uint32_t);
1478 pe_resource_t *rsc = va_arg(args, pe_resource_t *);
1479 GList *only_node = va_arg(args, GList *);
1480 GList *only_rsc = va_arg(args, GList *);
1481
1482 pe__bundle_variant_data_t *bundle_data = NULL;
1483 int rc = pcmk_rc_no_output;
1484 gboolean print_everything = TRUE;
1485
1486 get_bundle_variant_data(bundle_data, rsc);
1487
1488 CRM_ASSERT(rsc != NULL);
1489
1490 if (rsc->fns->is_filtered(rsc, only_rsc, TRUE)) {
1491 return rc;
1492 }
1493
1494 print_everything = pcmk__str_in_list(rsc->id, only_rsc, pcmk__str_star_matches);
1495
1496 for (GList *gIter = bundle_data->replicas; gIter != NULL;
1497 gIter = gIter->next) {
1498 pe__bundle_replica_t *replica = gIter->data;
1499 gboolean print_ip, print_child, print_ctnr, print_remote;
1500
1501 CRM_ASSERT(replica);
1502
1503 if (pcmk__rsc_filtered_by_node(replica->container, only_node)) {
1504 continue;
1505 }
1506
1507 print_ip = replica->ip != NULL &&
1508 !replica->ip->fns->is_filtered(replica->ip, only_rsc, print_everything);
1509 print_child = replica->child != NULL &&
1510 !replica->child->fns->is_filtered(replica->child, only_rsc, print_everything);
1511 print_ctnr = !replica->container->fns->is_filtered(replica->container, only_rsc, print_everything);
1512 print_remote = replica->remote != NULL &&
1513 !replica->remote->fns->is_filtered(replica->remote, only_rsc, print_everything);
1514
1515 if (pcmk_is_set(show_opts, pcmk_show_implicit_rscs) ||
1516 (print_everything == FALSE && (print_ip || print_child || print_ctnr || print_remote))) {
1517
1518
1519
1520 uint32_t new_show_opts = show_opts | pcmk_show_implicit_rscs;
1521
1522 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Container bundle%s: %s [%s]%s%s",
1523 (bundle_data->nreplicas > 1)? " set" : "",
1524 rsc->id, bundle_data->image,
1525 pcmk_is_set(rsc->flags, pe_rsc_unique) ? " (unique)" : "",
1526 pcmk_is_set(rsc->flags, pe_rsc_managed) ? "" : " (unmanaged)");
1527
1528 if (pcmk__list_of_multiple(bundle_data->replicas)) {
1529 out->list_item(out, NULL, "Replica[%d]", replica->offset);
1530 }
1531
1532 out->begin_list(out, NULL, NULL, NULL);
1533
1534 if (print_ip) {
1535 out->message(out, crm_map_element_name(replica->ip->xml),
1536 new_show_opts, replica->ip, only_node, only_rsc);
1537 }
1538
1539 if (print_child) {
1540 out->message(out, crm_map_element_name(replica->child->xml),
1541 new_show_opts, replica->child, only_node, only_rsc);
1542 }
1543
1544 if (print_ctnr) {
1545 out->message(out, crm_map_element_name(replica->container->xml),
1546 new_show_opts, replica->container, only_node, only_rsc);
1547 }
1548
1549 if (print_remote) {
1550 out->message(out, crm_map_element_name(replica->remote->xml),
1551 new_show_opts, replica->remote, only_node, only_rsc);
1552 }
1553
1554 out->end_list(out);
1555 } else if (print_everything == FALSE && !(print_ip || print_child || print_ctnr || print_remote)) {
1556 continue;
1557 } else {
1558 PCMK__OUTPUT_LIST_HEADER(out, FALSE, rc, "Container bundle%s: %s [%s]%s%s",
1559 (bundle_data->nreplicas > 1)? " set" : "",
1560 rsc->id, bundle_data->image,
1561 pcmk_is_set(rsc->flags, pe_rsc_unique) ? " (unique)" : "",
1562 pcmk_is_set(rsc->flags, pe_rsc_managed) ? "" : " (unmanaged)");
1563
1564 pe__bundle_replica_output_text(out, replica, pe__current_node(replica->container),
1565 show_opts);
1566 }
1567 }
1568
1569 PCMK__OUTPUT_LIST_FOOTER(out, rc);
1570 return rc;
1571 }
1572
1573
1574
1575
1576
1577 static void
1578 print_bundle_replica(pe__bundle_replica_t *replica, const char *pre_text,
1579 long options, void *print_data)
1580 {
1581 pe_node_t *node = NULL;
1582 pe_resource_t *rsc = replica->child;
1583
1584 int offset = 0;
1585 char buffer[LINE_MAX];
1586
1587 if(rsc == NULL) {
1588 rsc = replica->container;
1589 }
1590
1591 if (replica->remote) {
1592 offset += snprintf(buffer + offset, LINE_MAX - offset, "%s",
1593 rsc_printable_id(replica->remote));
1594 } else {
1595 offset += snprintf(buffer + offset, LINE_MAX - offset, "%s",
1596 rsc_printable_id(replica->container));
1597 }
1598 if (replica->ipaddr) {
1599 offset += snprintf(buffer + offset, LINE_MAX - offset, " (%s)",
1600 replica->ipaddr);
1601 }
1602
1603 node = pe__current_node(replica->container);
1604 common_print(rsc, pre_text, buffer, node, options, print_data);
1605 }
1606
1607
1608
1609
1610
1611 void
1612 pe__print_bundle(pe_resource_t *rsc, const char *pre_text, long options,
1613 void *print_data)
1614 {
1615 pe__bundle_variant_data_t *bundle_data = NULL;
1616 char *child_text = NULL;
1617 CRM_CHECK(rsc != NULL, return);
1618
1619 if (options & pe_print_xml) {
1620 bundle_print_xml(rsc, pre_text, options, print_data);
1621 return;
1622 }
1623
1624 get_bundle_variant_data(bundle_data, rsc);
1625
1626 if (pre_text == NULL) {
1627 pre_text = " ";
1628 }
1629
1630 status_print("%sContainer bundle%s: %s [%s]%s%s\n",
1631 pre_text, ((bundle_data->nreplicas > 1)? " set" : ""),
1632 rsc->id, bundle_data->image,
1633 pcmk_is_set(rsc->flags, pe_rsc_unique) ? " (unique)" : "",
1634 pcmk_is_set(rsc->flags, pe_rsc_managed) ? "" : " (unmanaged)");
1635 if (options & pe_print_html) {
1636 status_print("<br />\n<ul>\n");
1637 }
1638
1639
1640 for (GList *gIter = bundle_data->replicas; gIter != NULL;
1641 gIter = gIter->next) {
1642 pe__bundle_replica_t *replica = gIter->data;
1643
1644 CRM_ASSERT(replica);
1645 if (options & pe_print_html) {
1646 status_print("<li>");
1647 }
1648
1649 if (pcmk_is_set(options, pe_print_implicit)) {
1650 child_text = crm_strdup_printf(" %s", pre_text);
1651 if (pcmk__list_of_multiple(bundle_data->replicas)) {
1652 status_print(" %sReplica[%d]\n", pre_text, replica->offset);
1653 }
1654 if (options & pe_print_html) {
1655 status_print("<br />\n<ul>\n");
1656 }
1657 print_rsc_in_list(replica->ip, child_text, options, print_data);
1658 print_rsc_in_list(replica->container, child_text, options, print_data);
1659 print_rsc_in_list(replica->remote, child_text, options, print_data);
1660 print_rsc_in_list(replica->child, child_text, options, print_data);
1661 if (options & pe_print_html) {
1662 status_print("</ul>\n");
1663 }
1664 } else {
1665 child_text = crm_strdup_printf("%s ", pre_text);
1666 print_bundle_replica(replica, child_text, options, print_data);
1667 }
1668 free(child_text);
1669
1670 if (options & pe_print_html) {
1671 status_print("</li>\n");
1672 }
1673 }
1674 if (options & pe_print_html) {
1675 status_print("</ul>\n");
1676 }
1677 }
1678
1679 static void
1680 free_bundle_replica(pe__bundle_replica_t *replica)
1681 {
1682 if (replica == NULL) {
1683 return;
1684 }
1685
1686 if (replica->node) {
1687 free(replica->node);
1688 replica->node = NULL;
1689 }
1690
1691 if (replica->ip) {
1692 free_xml(replica->ip->xml);
1693 replica->ip->xml = NULL;
1694 replica->ip->fns->free(replica->ip);
1695 replica->ip = NULL;
1696 }
1697 if (replica->container) {
1698 free_xml(replica->container->xml);
1699 replica->container->xml = NULL;
1700 replica->container->fns->free(replica->container);
1701 replica->container = NULL;
1702 }
1703 if (replica->remote) {
1704 free_xml(replica->remote->xml);
1705 replica->remote->xml = NULL;
1706 replica->remote->fns->free(replica->remote);
1707 replica->remote = NULL;
1708 }
1709 free(replica->ipaddr);
1710 free(replica);
1711 }
1712
1713 void
1714 pe__free_bundle(pe_resource_t *rsc)
1715 {
1716 pe__bundle_variant_data_t *bundle_data = NULL;
1717 CRM_CHECK(rsc != NULL, return);
1718
1719 get_bundle_variant_data(bundle_data, rsc);
1720 pe_rsc_trace(rsc, "Freeing %s", rsc->id);
1721
1722 free(bundle_data->prefix);
1723 free(bundle_data->image);
1724 free(bundle_data->control_port);
1725 free(bundle_data->host_network);
1726 free(bundle_data->host_netmask);
1727 free(bundle_data->ip_range_start);
1728 free(bundle_data->container_network);
1729 free(bundle_data->launcher_options);
1730 free(bundle_data->container_command);
1731 g_free(bundle_data->container_host_options);
1732
1733 g_list_free_full(bundle_data->replicas,
1734 (GDestroyNotify) free_bundle_replica);
1735 g_list_free_full(bundle_data->mounts, (GDestroyNotify)mount_free);
1736 g_list_free_full(bundle_data->ports, (GDestroyNotify)port_free);
1737 g_list_free(rsc->children);
1738
1739 if(bundle_data->child) {
1740 free_xml(bundle_data->child->xml);
1741 bundle_data->child->xml = NULL;
1742 bundle_data->child->fns->free(bundle_data->child);
1743 }
1744 common_free(rsc);
1745 }
1746
1747 enum rsc_role_e
1748 pe__bundle_resource_state(const pe_resource_t *rsc, gboolean current)
1749 {
1750 enum rsc_role_e container_role = RSC_ROLE_UNKNOWN;
1751 return container_role;
1752 }
1753
1754
1755
1756
1757
1758
1759
1760
1761 int
1762 pe_bundle_replicas(const pe_resource_t *rsc)
1763 {
1764 if ((rsc == NULL) || (rsc->variant != pe_container)) {
1765 return 0;
1766 } else {
1767 pe__bundle_variant_data_t *bundle_data = NULL;
1768
1769 get_bundle_variant_data(bundle_data, rsc);
1770 return bundle_data->nreplicas;
1771 }
1772 }
1773
1774 void
1775 pe__count_bundle(pe_resource_t *rsc)
1776 {
1777 pe__bundle_variant_data_t *bundle_data = NULL;
1778
1779 get_bundle_variant_data(bundle_data, rsc);
1780 for (GList *item = bundle_data->replicas; item != NULL; item = item->next) {
1781 pe__bundle_replica_t *replica = item->data;
1782
1783 if (replica->ip) {
1784 replica->ip->fns->count(replica->ip);
1785 }
1786 if (replica->child) {
1787 replica->child->fns->count(replica->child);
1788 }
1789 if (replica->container) {
1790 replica->container->fns->count(replica->container);
1791 }
1792 if (replica->remote) {
1793 replica->remote->fns->count(replica->remote);
1794 }
1795 }
1796 }
1797
1798 gboolean
1799 pe__bundle_is_filtered(pe_resource_t *rsc, GList *only_rsc, gboolean check_parent)
1800 {
1801 gboolean passes = FALSE;
1802 pe__bundle_variant_data_t *bundle_data = NULL;
1803
1804 if (pcmk__str_in_list(rsc_printable_id(rsc), only_rsc, pcmk__str_star_matches)) {
1805 passes = TRUE;
1806 } else {
1807 get_bundle_variant_data(bundle_data, rsc);
1808
1809 for (GList *gIter = bundle_data->replicas; gIter != NULL; gIter = gIter->next) {
1810 pe__bundle_replica_t *replica = gIter->data;
1811
1812 if (replica->ip != NULL && !replica->ip->fns->is_filtered(replica->ip, only_rsc, FALSE)) {
1813 passes = TRUE;
1814 break;
1815 } else if (replica->child != NULL && !replica->child->fns->is_filtered(replica->child, only_rsc, FALSE)) {
1816 passes = TRUE;
1817 break;
1818 } else if (!replica->container->fns->is_filtered(replica->container, only_rsc, FALSE)) {
1819 passes = TRUE;
1820 break;
1821 } else if (replica->remote != NULL && !replica->remote->fns->is_filtered(replica->remote, only_rsc, FALSE)) {
1822 passes = TRUE;
1823 break;
1824 }
1825 }
1826 }
1827
1828 return !passes;
1829 }