Resilient stack: add promise for ssh key presence of PBS in root instanec.
[slapos.git] / stack / resilient / template-replicated.cfg.in
1 {% macro replicate(namebase, nbbackup, typeexport, typeimport, heriteLeader='', heriteBackup='', slapparameter_dict={}) %}
2
3 {% set sla_parameter_dict = {} -%}
4 # prepare sla-parameters
5 {% if slapparameter_dict is defined -%}
6 {%   for key in slapparameter_dict.keys() -%}
7 {%     if key.startswith('-sla-') -%}
8 {%       do sla_parameter_dict.__setitem__(key, slapparameter_dict.pop(key)) -%}
9 {%     endif -%}
10 {%   endfor -%}
11 {% endif -%}
12
13
14 [resilient-directory]
15 recipe = slapos.cookbook:mkdirectory
16 home = ${buildout:directory}
17 etc = ${:home}/etc
18 promise = ${:etc}/promise
19
20
21 ## Tells the Backupable recipe that we want a backup
22 [resilient]
23 recipe = slapos.cookbook:request
24 config-namebase = {{namebase}}
25 software-url = ${slap-connection:software-release-url}
26
27 ## Every request is double to provide the 3 IPs.
28 ## First, we request with ip-list parameter hardcoded.
29 ## Then, we request the same thing without this.
30 ## XXX-Cedric: is it useful?
31 [request-{{namebase}}]
32 <= resilient
33    slap-connection
34    {{heriteLeader}}
35 software-type = {{typeexport}}
36 name = {{namebase}}0
37 return = ssh-public-key ssh-url notification-id ip
38 config =
39 # Resilient related parameters
40   number authorized-key notify ip-list namebase
41 {% if slapparameter_dict is defined %}
42 # Software Instance related parameters
43   {% for parameter_name in slapparameter_dict.keys() %}{{parameter_name}} {% endfor %}
44 {% endif %}
45 config-number = 0
46 config-authorized-key = {% for id in range(1,nbbackup|int) %} ${request-pbs-{{namebase}}-{{id}}:connection-ssh-key}{% endfor %}
47 config-notify = {% for id in range(1,nbbackup|int) %} ${request-pbs-{{namebase}}-{{id}}:connection-notification-url}{% endfor %}
48 config-ip-list =
49 # Bubble up all the instance parameters to the requested export instance.
50 {% if slapparameter_dict is defined %}
51 {% for parameter_name, parameter_value in slapparameter_dict.items() %}config-{{parameter_name}} = {{parameter_value}}
52 {% endfor %}
53 {% endif %}
54 {% if sla_parameter_dict -%}
55 {%   set sla_key_main = "-sla-%s%s-" % (namebase, 0) -%}
56 {%   set sla_key_secondary = "-sla-%s-" % (0) -%}
57 {%   set sla_key_main_length = sla_key_main | length -%}
58 {%   set sla_key_secondary_length = sla_key_secondary | length -%}
59 {%   set sla_dict = {} -%}
60 {%   for key in sla_parameter_dict.keys() -%}
61 {%     if key.startswith(sla_key_main) -%}
62 {%       do sla_dict.__setitem__(key[sla_key_main_length:], sla_parameter_dict.get(key)) -%}
63 {%     elif key.startswith(sla_key_secondary) and not sla_dict.has_key(key[sla_key_secondary_length:]) -%}
64 {%         do sla_dict.__setitem__(key[sla_key_secondary_length:], sla_parameter_dict.get(key)) -%}
65 {%     endif -%}
66 {%   endfor -%}
67 {%   if sla_dict %}
68 sla = {{ ' '.join(sla_dict.keys()) }}
69 {%     for key, value in sla_dict.iteritems() -%}
70 sla-{{ key }} = {{ value }}
71 {%     endfor -%}
72 {%   endif -%}
73 {% endif -%}
74
75
76 {% for id in range(1,nbbackup|int) %}
77
78 [request-{{namebase}}-pseudo-replicating-{{id}}]
79 <= slap-connection
80    resilient
81    {{heriteBackup}}
82 recipe = slapos.cookbook:request
83 name = {{namebase}}{{id}}
84
85 software-url = ${slap-connection:software-release-url}
86 software-type = {{typeimport}}
87 return = ssh-public-key ssh-url notification-url ip
88
89 pbs-notification-id = ${slap-connection:computer-id}-${slap-connection:partition-id}-{{namebase}}-{{id}}-push
90
91 config = number authorized-key on-notification ip-list namebase
92 config-number = {{id}}
93 config-authorized-key = ${request-pbs-{{namebase}}-{{id}}:connection-ssh-key}
94 config-on-notification = ${request-pbs-{{namebase}}-{{id}}:connection-feeds-url}${:pbs-notification-id}
95 config-ip-list =
96 {% if sla_parameter_dict -%}
97 {%   set sla_key_main = "-sla-%s%s-" % (namebase, id) -%}
98 {%   set sla_key_secondary = "-sla-%s-" % (id) -%}
99 {%   set sla_key_main_length = sla_key_main | length -%}
100 {%   set sla_key_secondary_length = sla_key_secondary | length -%}
101 {%   set sla_dict = {} -%}
102 {%   for key in sla_parameter_dict.keys() -%}
103 {%     if key.startswith(sla_key_main) -%}
104 {%       do sla_dict.__setitem__(key[sla_key_main_length:], sla_parameter_dict.get(key)) -%}
105 {%     elif key.startswith(sla_key_secondary) and not sla_dict.has_key(key[sla_key_secondary_length:]) -%}
106 {%         do sla_dict.__setitem__(key[sla_key_secondary_length:], sla_parameter_dict.get(key)) -%}
107 {%     endif -%}
108 {%   endfor -%}
109 {%   if sla_dict %}
110 sla = {{ ' '.join(sla_dict.keys()) }}
111 {%     for key, value in sla_dict.iteritems() -%}
112 sla-{{ key }} = {{ value }}
113 {%     endfor -%}
114 {%   endif %}
115 {% endif %}
116
117 {% endfor -%}
118
119
120 [iplist]
121 config-ip-list = ${request-{{namebase}}:connection-ip}{% for j in range(1,nbbackup|int) %} ${request-{{namebase}}-pseudo-replicating-{{j}}:connection-ip}{% endfor %}
122
123 [request-{{namebase}}-2]
124 <= request-{{namebase}}
125    iplist
126
127 [resilient-request-{{namebase}}-public-key-promise]
128 # Check that public-key-value parameter exists and is not empty
129 # XXX: maybe we should consider empty values to be non-nexistent.
130 recipe = collective.recipe.template
131 # XXX: don't use system executable
132 input = inline:#!/bin/sh
133   PUBLIC_KEY_CONTENT="${request-{{namebase}}-2:connection-ssh-public-key})"
134   if [[ ! -n "$PUBLIC_KEY_CONTENT" -o "$PUBLIC_KEY_CONTENT" == None ]]; then
135     exit 1
136   fi
137 output = ${resilient-directory:promise}/resilient-request-{{namebase}}-public-key
138 mode = 700
139
140 {% for id in range(1,nbbackup|int) %}
141 [request-{{namebase}}-pseudo-replicating-{{id}}-2]
142 <= request-{{namebase}}-pseudo-replicating-{{id}}
143    iplist
144
145 [resilient-request-{{namebase}}-pseudo-replicating-{{id}}-public-key-promise]
146 # Check that public-key-value parameter exists and is not empty
147 # XXX: maybe we should consider empty values to be non-nexistent.
148 recipe = collective.recipe.template
149 # XXX: don't use system executable
150 input = inline:#!/bin/sh
151   PUBLIC_KEY_CONTENT="${request-{{namebase}}-pseudo-replicating-{{id}}-2:connection-ssh-public-key})"
152   if [ ! -n "$PUBLIC_KEY_CONTENT" -a  "$PUBLIC_KEY_CONTENT" == None ]; then
153     exit 1
154   fi
155 output = ${resilient-directory:promise}/resilient-request-{{namebase}}-pseudo-replicating-{{id}}-public-key
156 mode = 700
157
158 {% endfor %}
159
160
161
162 ## The PBS and their push / pull slaves
163 ## Adding a PBS provides resiliency
164 ## Adding a backup server provides availability
165
166 ## Having 3 backups pulling from the same PBS provides
167 ##only availability, not resiliency
168
169 [request-pbs-common]
170 <= slap-connection
171 recipe = slapos.cookbook:request
172 software-url = ${slap-connection:software-release-url}
173 software-type = pull-backup
174
175 {% for id in range(1,nbbackup|int) %}
176
177 [request-pbs-{{namebase}}-{{id}}]
178 <= request-pbs-common
179 name = PBS ({{namebase}} / {{id}})
180 return = ssh-key notification-url feeds-url
181 slave = false
182 {% if sla_parameter_dict -%}
183 {%   set sla_key_main = "-sla-%s%s-" % ("pbs", id) -%}
184 {%   set sla_key_secondary = "-sla-%s-" % (id) -%}
185 {%   set sla_key_main_length = sla_key_main | length -%}
186 {%   set sla_key_secondary_length = sla_key_secondary | length -%}
187 {%   set sla_dict = {} -%}
188 {%   for key in sla_parameter_dict.keys() -%}
189 {%     if key.startswith(sla_key_main) -%}
190 {%       do sla_dict.__setitem__(key[sla_key_main_length:], sla_parameter_dict.get(key)) -%}
191 {%     elif key.startswith(sla_key_secondary) and not sla_dict.has_key(key[sla_key_secondary_length:]) -%}
192 {%         do sla_dict.__setitem__(key[sla_key_secondary_length:], sla_parameter_dict.get(key)) -%}
193 {%     endif -%}
194 {%   endfor -%}
195 {%   if sla_dict %}
196 sla = {{ ' '.join(sla_dict.keys()) }}
197 {%     for key, value in sla_dict.iteritems() -%}
198 sla-{{ key }} = {{ value }}
199 {%     endfor %}
200 {%   endif %}
201 {% endif %}
202
203 [resilient-request-pbs-{{namebase}}-{{id}}-public-key-promise]
204 # Check that public-key-value parameter exists and is not empty
205 # XXX: maybe we should consider empty values to be non-nexistent.
206 recipe = collective.recipe.template
207 # XXX: don't use system executable
208 input = inline:#!/bin/sh
209   PUBLIC_KEY_CONTENT="${request-pbs-{{namebase}}-{{id}}:connection-ssh-key}:connection-ssh-key})"
210   if [ ! -n "$PUBLIC_KEY_CONTENT" -a  "$PUBLIC_KEY_CONTENT" == None ]; then
211     exit 1
212   fi
213 output = ${resilient-directory:promise}/resilient-request-{{namebase}}-pseudo-replicating-{{id}}-public-key
214 mode = 700
215
216
217 [request-pull-backup-server-{{namebase}}-{{id}}]
218 <= request-pbs-common
219 name = PBS {{id}} pulling from ${request-{{namebase}}:name}
220 config = url name type server-key on-notification notify notification-id title remove-backup-older-than
221 config-url = ${request-{{namebase}}:connection-ssh-url}
222 config-type = pull
223 config-server-key = ${request-{{namebase}}:connection-ssh-public-key}
224 config-on-notification = ${request-{{namebase}}:connection-notification-id}
225 config-notify = ${request-pbs-{{namebase}}-{{id}}:connection-notification-url}
226 config-notification-id = ${slap-connection:computer-id}-${slap-connection:partition-id}-{{namebase}}-{{id}}-pull
227 config-name = ${slap-connection:computer-id}-${slap-connection:partition-id}-{{namebase}}-{{id}}
228 config-title = Pulling from {{namebase}}
229 config-remove-backup-older-than = {{ slapparameter_dict.get('remove-backup-older-than', '3B') }}
230 slave = true
231 sla = instance_guid
232 sla-instance_guid = ${request-pbs-{{namebase}}-{{id}}:instance_guid}
233
234 [request-pull-backup-server-{{namebase}}-backup-{{id}}]
235 <= request-pbs-common
236 name = PBS pushing on ${request-{{namebase}}-pseudo-replicating-{{id}}:name}
237 config = url name type server-key on-notification notify notification-id title
238 config-url = ${request-{{namebase}}-pseudo-replicating-{{id}}:connection-ssh-url}
239 config-type = push
240 config-server-key = ${request-{{namebase}}-pseudo-replicating-{{id}}:connection-ssh-public-key}
241 config-on-notification = ${request-pbs-{{namebase}}-{{id}}:connection-feeds-url}${request-pull-backup-server-{{namebase}}-{{id}}:config-notification-id}
242 config-notify = ${request-{{namebase}}-pseudo-replicating-{{id}}:connection-notification-url}
243 config-notification-id = ${request-{{namebase}}-pseudo-replicating-{{id}}:pbs-notification-id}
244 config-name = ${slap-connection:computer-id}-${slap-connection:partition-id}-{{namebase}}-{{id}}
245 config-title = Pushing to {{namebase}} backup {{id}}
246 slave = true
247 sla = instance_guid
248 sla-instance_guid = ${request-pbs-{{namebase}}-{{id}}:instance_guid}
249 {% endfor %}
250
251 [slap-parameter]
252 # Default parameters for distributed deployment
253 # I.e state "backup1 of maria should go there, ..."
254 {% for id in range(1,nbbackup|int) %}
255 {{namebase}}{{id}}-computer-guid =
256 pbs-{{namebase}}{{id}}-computer-guid =
257 {% endfor %}
258
259 {% endmacro %}
260