27 #define VARIANT_CONTAINER 1 33 next_ip(
const char *last_ip)
35 unsigned int oct1 = 0;
36 unsigned int oct2 = 0;
37 unsigned int oct3 = 0;
38 unsigned int oct4 = 0;
39 int rc = sscanf(last_ip,
"%u.%u.%u.%u", &oct1, &oct2, &oct3, &oct4);
45 }
else if (oct3 > 253) {
48 }
else if (oct4 > 253) {
60 allocate_ip(container_variant_data_t *
data, container_grouping_t *tuple,
char *buffer,
int max)
62 if(data->ip_range_start == NULL) {
65 }
else if(data->ip_last) {
66 tuple->ipaddr = next_ip(data->ip_last);
69 tuple->ipaddr = strdup(data->ip_range_start);
72 data->ip_last = tuple->ipaddr;
74 return snprintf(buffer, max,
" --add-host=%s-%d:%s --link %s-docker-%d:%s-link-%d",
75 data->prefix, tuple->offset, tuple->ipaddr,
76 data->prefix, tuple->offset, data->prefix, tuple->offset);
78 return snprintf(buffer, max,
" --add-host=%s-%d:%s",
79 data->prefix, tuple->offset, tuple->ipaddr);
84 create_resource(
const char *name,
const char *provider,
const char *kind)
97 create_nvp(xmlNode *parent,
const char *name,
const char *value)
107 create_op(xmlNode *parent,
const char *prefix,
const char *task,
const char *interval)
129 valid_network(container_variant_data_t *data)
131 if(data->ip_range_start) {
134 if(data->control_port) {
135 if(data->replicas_per_host > 1) {
136 pe_err(
"Specifying the 'control-port' for %s requires 'replicas-per-host=1'", data->prefix);
137 data->replicas_per_host = 1;
147 resource_t *parent, container_variant_data_t *data, container_grouping_t *tuple,
150 if(data->ip_range_start) {
152 xmlNode *xml_ip = NULL;
153 xmlNode *xml_obj = NULL;
157 xml_ip = create_resource(
id,
"heartbeat",
"IPaddr2");
161 crm_xml_set_id(xml_obj,
"%s-attributes-%d", data->prefix, tuple->offset);
163 create_nvp(xml_obj,
"ip", tuple->ipaddr);
164 if(data->host_network) {
165 create_nvp(xml_obj,
"nic", data->host_network);
168 if(data->host_netmask) {
169 create_nvp(xml_obj,
"cidr_netmask", data->host_netmask);
172 create_nvp(xml_obj,
"cidr_netmask",
"32");
176 create_op(xml_obj,
ID(xml_ip),
"monitor",
"60s");
180 if (
common_unpack(xml_ip, &tuple->ip, parent, data_set) ==
false) {
190 create_docker_resource(
191 resource_t *parent, container_variant_data_t *data, container_grouping_t *tuple,
194 int offset = 0, max = 4096;
195 char *buffer = calloc(1, max+1);
197 int doffset = 0, dmax = 1024;
198 char *dbuffer = calloc(1, dmax+1);
201 xmlNode *xml_docker = NULL;
202 xmlNode *xml_obj = NULL;
206 xml_docker = create_resource(
id,
"heartbeat",
"docker");
210 crm_xml_set_id(xml_obj,
"%s-attributes-%d", data->prefix, tuple->offset);
212 create_nvp(xml_obj,
"image", data->image);
213 create_nvp(xml_obj,
"allow_pull",
"true");
214 create_nvp(xml_obj,
"force_kill",
"false");
215 create_nvp(xml_obj,
"reuse",
"false");
217 offset += snprintf(buffer+offset, max-offset,
" --restart=no");
224 if (data->ip_range_start != NULL) {
225 offset += snprintf(buffer+offset, max-offset,
" -h %s-%d",
226 data->prefix, tuple->offset);
229 if(data->docker_network) {
231 offset += snprintf(buffer+offset, max-offset,
" --net=%s", data->docker_network);
234 if(data->control_port) {
235 offset += snprintf(buffer+offset, max-offset,
" -e PCMK_remote_port=%s", data->control_port);
237 offset += snprintf(buffer+offset, max-offset,
" -e PCMK_remote_port=%d",
DEFAULT_REMOTE_PORT);
240 for(
GListPtr pIter = data->mounts; pIter != NULL; pIter = pIter->next) {
241 container_mount_t *mount = pIter->data;
245 "%s/%s-%d", mount->source, data->prefix, tuple->offset);
248 doffset += snprintf(dbuffer+doffset, dmax-doffset,
",");
250 doffset += snprintf(dbuffer+doffset, dmax-doffset,
"%s", source);
251 offset += snprintf(buffer+offset, max-offset,
" -v %s:%s", source, mount->target);
255 offset += snprintf(buffer+offset, max-offset,
" -v %s:%s", mount->source, mount->target);
258 offset += snprintf(buffer+offset, max-offset,
":%s", mount->options);
262 for(
GListPtr pIter = data->ports; pIter != NULL; pIter = pIter->next) {
263 container_port_t *port = pIter->data;
266 offset += snprintf(buffer+offset, max-offset,
" -p %s:%s:%s",
267 tuple->ipaddr, port->source, port->target);
269 offset += snprintf(buffer+offset, max-offset,
" -p %s:%s", port->source, port->target);
273 if(data->docker_run_options) {
274 offset += snprintf(buffer+offset, max-offset,
" %s", data->docker_run_options);
277 if(data->docker_host_options) {
278 offset += snprintf(buffer+offset, max-offset,
" %s", data->docker_host_options);
281 create_nvp(xml_obj,
"run_opts", buffer);
284 create_nvp(xml_obj,
"mount_points", dbuffer);
288 if(data->docker_run_command) {
289 create_nvp(xml_obj,
"run_cmd", data->docker_run_command);
291 create_nvp(xml_obj,
"run_cmd",
SBIN_DIR"/pacemaker_remoted");
299 create_nvp(xml_obj,
"monitor_cmd",
"/bin/true");
313 if(data->docker_run_command) {
314 create_nvp(xml_obj,
"run_cmd", data->docker_run_command);
322 create_nvp(xml_obj,
"monitor_cmd",
"/bin/true");
327 create_op(xml_obj,
ID(xml_docker),
"monitor",
"60s");
331 if (
common_unpack(xml_docker, &tuple->docker, parent, data_set) == FALSE) {
347 gpointer match = g_hash_table_lookup(rsc->
allowed_nodes, uname);
355 for (child = rsc->
children; child != NULL; child = child->next) {
356 disallow_node((
resource_t *) (child->data), uname);
362 create_remote_resource(
363 resource_t *parent, container_variant_data_t *data, container_grouping_t *tuple,
366 if (tuple->child && valid_network(data)) {
370 xmlNode *xml_obj = NULL;
371 xmlNode *xml_remote = NULL;
373 const char *uname = NULL;
378 id =
crm_strdup_printf(
"pcmk-internal-%s-remote-%d", tuple->child->id, tuple->offset);
382 xml_remote = create_resource(
id,
"pacemaker",
"remote");
390 uname =
ID(xml_remote);
393 create_op(xml_obj, uname,
"monitor",
"60s");
396 crm_xml_set_id(xml_obj,
"%s-attributes-%d", data->prefix, tuple->offset);
399 create_nvp(xml_obj,
"addr", tuple->ipaddr);
402 create_nvp(xml_obj,
"addr",
"#uname");
405 if(data->control_port) {
406 create_nvp(xml_obj,
"port", data->control_port);
410 create_nvp(xml_obj,
"port", port_s);
415 crm_xml_set_id(xml_obj,
"%s-meta-%d", data->prefix, tuple->offset);
455 for (rsc_iter = data_set->
resources; rsc_iter; rsc_iter = rsc_iter->next) {
456 disallow_node((
resource_t *) (rsc_iter->data), uname);
460 tuple->node->weight = 500;
462 if (
common_unpack(xml_remote, &tuple->remote, parent, data_set) == FALSE) {
466 g_hash_table_iter_init(&gIter, tuple->remote->allowed_nodes);
467 while (g_hash_table_iter_next(&gIter, NULL, (
void **)&node)) {
474 tuple->node->details->remote_rsc = tuple->remote;
481 g_hash_table_insert(tuple->node->details->attrs,
482 strdup(
"#kind"), strdup(
"container"));
500 resource_t *parent, container_variant_data_t *data, container_grouping_t *tuple,
504 if(create_docker_resource(parent, data, tuple, data_set) == FALSE) {
507 if(create_ip_resource(parent, data, tuple, data_set) == FALSE) {
510 if(create_remote_resource(parent, data, tuple, data_set) == FALSE) {
513 if(tuple->child && tuple->ipaddr) {
533 static void mount_free(container_mount_t *mount)
537 free(mount->options);
541 static void port_free(container_port_t *port)
551 const char *value = NULL;
552 xmlNode *xml_obj = NULL;
553 xmlNode *xml_resource = NULL;
554 container_variant_data_t *container_data = NULL;
559 container_data = calloc(1,
sizeof(container_variant_data_t));
561 container_data->prefix = strdup(rsc->
id);
564 if(xml_obj == NULL) {
570 if (container_data->masters < 0) {
571 pe_err(
"'masters' for %s must be nonnegative integer, using 0",
573 container_data->masters = 0;
577 if ((value == NULL) && (container_data->masters > 0)) {
578 container_data->replicas = container_data->masters;
582 if (container_data->replicas < 1) {
583 pe_err(
"'replicas' for %s must be positive integer, using 1", rsc->
id);
584 container_data->replicas = 1;
593 container_data->replicas_per_host =
crm_parse_int(value,
"1");
594 if (container_data->replicas_per_host < 1) {
595 pe_err(
"'replicas-per-host' for %s must be positive integer, using 1",
597 container_data->replicas_per_host = 1;
599 if (container_data->replicas_per_host == 1) {
616 for (xmlNode *xml_child = __xml_first_child_element(xml_obj); xml_child != NULL;
617 xml_child = __xml_next_element(xml_child)) {
619 container_port_t *port = calloc(1,
sizeof(container_port_t));
622 if(port->source == NULL) {
628 if(port->source != NULL && strlen(port->source) > 0) {
629 if(port->target == NULL) {
630 port->target = strdup(port->source);
632 container_data->ports = g_list_append(container_data->ports, port);
635 pe_err(
"Invalid port directive %s",
ID(xml_child));
642 for (xmlNode *xml_child = __xml_first_child_element(xml_obj); xml_child != NULL;
643 xml_child = __xml_next_element(xml_child)) {
645 container_mount_t *mount = calloc(1,
sizeof(container_mount_t));
648 if(mount->source == NULL) {
655 if(mount->source && mount->target) {
656 container_data->mounts = g_list_append(container_data->mounts, mount);
658 pe_err(
"Invalid mount directive %s",
ID(xml_child));
664 if (xml_obj && valid_network(container_data)) {
666 xmlNode *xml_set = NULL;
668 if(container_data->masters > 0) {
675 crm_xml_set_id(xml_resource,
"%s-%s", container_data->prefix, xml_resource->name);
678 crm_xml_set_id(xml_set,
"%s-%s-meta", container_data->prefix, xml_resource->name);
682 value =
crm_itoa(container_data->replicas);
686 value =
crm_itoa(container_data->replicas_per_host);
690 if(container_data->replicas_per_host > 1) {
696 if(container_data->masters) {
697 value =
crm_itoa(container_data->masters);
706 pe_err(
"Cannot control %s inside %s without either ip-range-start or control-port",
707 rsc->
id,
ID(xml_obj));
715 container_mount_t *mount = NULL;
716 container_port_t *port = NULL;
718 int offset = 0, max = 1024;
721 if (
common_unpack(xml_resource, &new_rsc, rsc, data_set) == FALSE) {
722 pe_err(
"Failed unpacking resource %s",
ID(rsc->
xml));
723 if (new_rsc != NULL && new_rsc->
fns != NULL) {
729 container_data->child = new_rsc;
731 mount = calloc(1,
sizeof(container_mount_t));
734 mount->options = NULL;
736 container_data->mounts = g_list_append(container_data->mounts, mount);
738 mount = calloc(1,
sizeof(container_mount_t));
740 mount->target = strdup(
"/var/log");
741 mount->options = NULL;
743 container_data->mounts = g_list_append(container_data->mounts, mount);
745 port = calloc(1,
sizeof(container_port_t));
746 if(container_data->control_port) {
747 port->source = strdup(container_data->control_port);
751 port->target = strdup(port->source);
752 container_data->ports = g_list_append(container_data->ports, port);
754 buffer = calloc(1, max+1);
755 for(childIter = container_data->child->children; childIter != NULL; childIter = childIter->next) {
756 container_grouping_t *tuple = calloc(1,
sizeof(container_grouping_t));
757 tuple->child = childIter->data;
758 tuple->offset = lpc++;
760 offset += allocate_ip(container_data, tuple, buffer+offset, max-offset);
761 container_data->tuples = g_list_append(container_data->tuples, tuple);
763 container_data->docker_host_options = buffer;
767 int offset = 0, max = 1024;
768 char *buffer = calloc(1, max+1);
770 for(
int lpc = 0; lpc < container_data->replicas; lpc++) {
771 container_grouping_t *tuple = calloc(1,
sizeof(container_grouping_t));
773 offset += allocate_ip(container_data, tuple, buffer+offset, max-offset);
774 container_data->tuples = g_list_append(container_data->tuples, tuple);
777 container_data->docker_host_options = buffer;
781 for (
GListPtr gIter = container_data->tuples; gIter != NULL; gIter = gIter->next) {
782 container_grouping_t *tuple = (container_grouping_t *)gIter->data;
784 create_container(rsc, container_data, tuple, data_set);
787 if(container_data->child) {
794 tuple_rsc_active(
resource_t *rsc, gboolean all)
797 gboolean child_active = rsc->
fns->
active(rsc, all);
799 if (child_active && !all) {
801 }
else if (!child_active && all) {
811 container_variant_data_t *container_data = NULL;
814 get_container_variant_data(container_data, rsc);
815 for (iter = container_data->tuples; iter != NULL; iter = iter->next) {
816 container_grouping_t *tuple = (container_grouping_t *)(iter->data);
819 rsc_active = tuple_rsc_active(tuple->ip, all);
820 if (rsc_active >= 0) {
821 return (gboolean) rsc_active;
824 rsc_active = tuple_rsc_active(tuple->child, all);
825 if (rsc_active >= 0) {
826 return (gboolean) rsc_active;
829 rsc_active = tuple_rsc_active(tuple->docker, all);
830 if (rsc_active >= 0) {
831 return (gboolean) rsc_active;
834 rsc_active = tuple_rsc_active(tuple->remote, all);
835 if (rsc_active >= 0) {
836 return (gboolean) rsc_active;
850 container_variant_data_t *container_data = NULL;
855 get_container_variant_data(container_data, parent);
858 for (
GListPtr gIter = container_data->tuples; gIter != NULL; gIter = gIter->next) {
859 container_grouping_t *tuple = (container_grouping_t *)gIter->data;
862 if(tuple->node->details == node->
details) {
878 print_rsc_in_list(
resource_t *rsc,
const char *pre_text,
long options,
885 rsc->
fns->
print(rsc, pre_text, options, print_data);
886 if (options & pe_print_html) {
893 container_print_xml(
resource_t * rsc,
const char *pre_text,
long options,
void *print_data)
895 container_variant_data_t *container_data = NULL;
896 char *child_text = NULL;
899 if (pre_text == NULL) {
904 get_container_variant_data(container_data, rsc);
915 for (
GListPtr gIter = container_data->tuples; gIter != NULL; gIter = gIter->next) {
916 container_grouping_t *tuple = (container_grouping_t *)gIter->data;
919 status_print(
"%s <replica id=\"%d\">\n", pre_text, tuple->offset);
920 print_rsc_in_list(tuple->ip, child_text, options, print_data);
921 print_rsc_in_list(tuple->child, child_text, options, print_data);
922 print_rsc_in_list(tuple->docker, child_text, options, print_data);
923 print_rsc_in_list(tuple->remote, child_text, options, print_data);
931 tuple_print(container_grouping_t * tuple,
const char *pre_text,
long options,
void *print_data)
937 char buffer[LINE_MAX];
944 offset += snprintf(buffer + offset, LINE_MAX - offset,
"%s",
rsc_printable_id(tuple->remote));
946 offset += snprintf(buffer + offset, LINE_MAX - offset,
"%s",
rsc_printable_id(tuple->docker));
949 offset += snprintf(buffer + offset, LINE_MAX - offset,
" (%s)", tuple->ipaddr);
952 if(tuple->docker && tuple->docker->running_on != NULL) {
953 node = tuple->docker->running_on->data;
954 }
else if (tuple->docker == NULL && rsc->
running_on != NULL) {
957 common_print(rsc, pre_text, buffer, node, options, print_data);
963 container_variant_data_t *container_data = NULL;
964 char *child_text = NULL;
968 container_print_xml(rsc, pre_text, options, print_data);
972 get_container_variant_data(container_data, rsc);
974 if (pre_text == NULL) {
979 pre_text, container_data->replicas>1?
" set":
"", rsc->
id, container_data->image,
987 for (
GListPtr gIter = container_data->tuples; gIter != NULL; gIter = gIter->next) {
988 container_grouping_t *tuple = (container_grouping_t *)gIter->data;
991 if (options & pe_print_html) {
997 if(g_list_length(container_data->tuples) > 1) {
998 status_print(
" %sReplica[%d]\n", pre_text, tuple->offset);
1000 if (options & pe_print_html) {
1003 print_rsc_in_list(tuple->ip, child_text, options, print_data);
1004 print_rsc_in_list(tuple->docker, child_text, options, print_data);
1005 print_rsc_in_list(tuple->remote, child_text, options, print_data);
1006 print_rsc_in_list(tuple->child, child_text, options, print_data);
1007 if (options & pe_print_html) {
1012 tuple_print(tuple, child_text, options, print_data);
1016 if (options & pe_print_html) {
1020 if (options & pe_print_html) {
1039 tuple->ip->xml = NULL;
1040 tuple->ip->fns->free(tuple->ip);
1045 tuple->docker->xml = NULL;
1046 tuple->docker->fns->free(tuple->docker);
1047 tuple->docker = NULL;
1051 tuple->remote->xml = NULL;
1052 tuple->remote->fns->free(tuple->remote);
1053 tuple->remote = NULL;
1055 free(tuple->ipaddr);
1062 container_variant_data_t *container_data = NULL;
1065 get_container_variant_data(container_data, rsc);
1068 free(container_data->prefix);
1069 free(container_data->image);
1070 free(container_data->control_port);
1071 free(container_data->host_network);
1072 free(container_data->host_netmask);
1073 free(container_data->ip_range_start);
1074 free(container_data->docker_network);
1075 free(container_data->docker_run_options);
1076 free(container_data->docker_run_command);
1077 free(container_data->docker_host_options);
1079 g_list_free_full(container_data->tuples, (GDestroyNotify)
tuple_free);
1080 g_list_free_full(container_data->mounts, (GDestroyNotify)mount_free);
1081 g_list_free_full(container_data->ports, (GDestroyNotify)port_free);
1084 if(container_data->child) {
1085 free_xml(container_data->child->xml);
1086 container_data->child->xml = NULL;
1087 container_data->child->fns->free(container_data->child);
1096 return container_role;
bool remote_id_conflict(const char *remote_name, pe_working_set_t *data)
#define CRM_CHECK(expr, failure_action)
gboolean safe_str_neq(const char *a, const char *b)
node_t * node_copy(const node_t *this_node)
node_t * pe_create_node(const char *id, const char *uname, const char *type, const char *score, pe_working_set_t *data_set)
void(* free)(resource_t *)
gboolean common_unpack(xmlNode *xml_obj, resource_t **rsc, resource_t *parent, pe_working_set_t *data_set)
void common_free(resource_t *rsc)
#define XML_LRM_ATTR_INTERVAL
#define status_print(fmt, args...)
int crm_parse_int(const char *text, const char *default_text)
char * crm_element_value_copy(xmlNode *data, const char *name)
#define XML_NVPAIR_ATTR_NAME
node_t * pe_find_node(GListPtr node_list, const char *uname)
resource_t * uber_parent(resource_t *rsc)
#define clear_bit(word, bit)
#define XML_CIB_TAG_NVPAIR
#define XML_RSC_ATTR_INCARNATION_MAX
#define pe_rsc_allow_remote_remotes
void crm_xml_sanitize_id(char *id)
Sanitize a string so it is usable as an XML ID.
#define DEFAULT_REMOTE_PORT
#define DEFAULT_REMOTE_KEY_LOCATION
#define XML_TAG_ATTR_SETS
gboolean is_remote_node(node_t *node)
struct node_shared_s * details
#define set_bit(word, bit)
#define XML_RSC_ATTR_CONTAINER
#define XML_CIB_TAG_RESOURCE
resource_object_functions_t * fns
GHashTable * allowed_nodes
xmlNode * add_node_copy(xmlNode *new_parent, xmlNode *xml_node)
#define XML_AGENT_ATTR_PROVIDER
#define XML_RSC_ATTR_ORDERED
#define XML_TAG_META_SETS
xmlNode * create_xml_node(xmlNode *parent, const char *name)
const char * crm_element_value(xmlNode *data, const char *name)
#define XML_RSC_ATTR_INCARNATION_NODEMAX
void free_xml(xmlNode *child)
#define XML_RSC_ATTR_UNIQUE
gboolean(* active)(resource_t *, gboolean)
void common_print(resource_t *rsc, const char *pre_text, const char *name, node_t *node, long options, void *print_data)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
#define XML_RSC_ATTR_MASTER_MAX
void(* print)(resource_t *, const char *, long, void *)
gboolean container_unpack(resource_t *rsc, pe_working_set_t *data_set)
enum rsc_role_e container_resource_state(const resource_t *rsc, gboolean current)
void tuple_free(container_grouping_t *tuple)
#define XML_CIB_TAG_INCARNATION
void add_hash_param(GHashTable *hash, const char *name, const char *value)
void crm_xml_set_id(xmlNode *xml, const char *format,...) __attribute__((__format__(__printf__
gboolean container_active(resource_t *rsc, gboolean all)
#define XML_NVPAIR_ATTR_VALUE
#define XML_CIB_TAG_MASTER
xmlNode * first_named_child(xmlNode *parent, const char *name)
#define pe_rsc_trace(rsc, fmt, args...)
char * crm_concat(const char *prefix, const char *suffix, char join)
char * crm_itoa(int an_int)
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
void container_print(resource_t *rsc, const char *pre_text, long options, void *print_data)
resource_t * find_container_child(const char *stem, resource_t *rsc, node_t *node)
const char * rsc_printable_id(resource_t *rsc)
#define XML_OP_ATTR_ALLOW_MIGRATE
#define XML_AGENT_ATTR_CLASS
void container_free(resource_t *rsc)