instance-kvm.cfg.jinja2 41.9 KB
Newer Older
1 2 3 4 5 6 7
{# Workaround empty parameter passing #}
{# In case of resilient '' is converted to 'None' string, but with slapproxy '' becomes None #}
{% for k, v in slapparameter_dict.items() %}
{%   if v == 'None' or v is none %}
{%     do slapparameter_dict.__setitem__(k, '') %}
{%   endif %}
{% endfor %}
8
{% set additional_frontend = slapparameter_dict.get('frontend-additional-instance-guid') %}
9 10 11 12 13
{% set enable_http = str(slapparameter_dict.get('enable-http-server', False)).lower() == 'true' -%}
{% set use_tap = str(slapparameter_dict.get('use-tap', True)).lower() == 'true' -%}
{% set use_nat = str(slapparameter_dict.get('use-nat', True)).lower() == 'true' -%}
{% set wipe_disk = str(slapparameter_dict.get('wipe-disk-ondestroy', False)).lower() == 'true' -%}
{% set nat_restrict = str(slapparameter_dict.get('nat-restrict-mode', False)).lower() == 'true' -%}
14
{% set name = slapparameter_dict.get('name', 'localhost') -%}
15
{% set disable_ansible_promise = str(slapparameter_dict.get('disable-ansible-promise', True)).lower() == 'true' -%}
16 17
{% set instance_type = slapparameter_dict.get('type', 'standalone') -%}
{% set nat_rule_list = slapparameter_dict.get('nat-rules', '22 80 443') -%}
18
{% set disk_device_path = slapparameter_dict.get('disk-device-path', None) -%}
19
{% set whitelist_domains = slapparameter_dict.get('whitelist-domains', '') -%}
20
{% set boot_image_url_list_enabled = 'boot-image-url-list' in slapparameter_dict %}
21
{% set boot_image_url_select_enabled = 'boot-image-url-select' in slapparameter_dict %}
22
{% set bootstrap_script_url = slapparameter_dict.get('bootstrap-script-url') -%}
23 24
{% set cpu_max_count = dumps(slapparameter_dict.get('cpu-max-count', int(slapparameter_dict.get('cpu-count', 1)) + 1)) %}
{% set ram_max_size = dumps(slapparameter_dict.get('ram-max-size', int(slapparameter_dict.get('ram-size', 1024)) + 512)) %}
Alain Takoudjou's avatar
Alain Takoudjou committed
25
{% set extends_list = [] -%}
26
{% set part_list = [] -%}
Alain Takoudjou's avatar
Alain Takoudjou committed
27

28 29 30 31 32 33 34
{% if instance_type == 'cluster' -%}
{% set nat_rule_list = slapparameter_dict.get('nat-rules', '') %}
{% endif -%}
{% if not nat_rule_list or not nat_rule_list.strip() -%}
{%   set nat_rule_list = '' %}
{% endif -%}

Alain Takoudjou's avatar
Alain Takoudjou committed
35 36
{% do extends_list.append(template_monitor) -%}
{% do extends_list.append(logrotate_cfg) -%}
37

38 39 40 41
[slap-network-information]
local-ipv4 = {{ slap_configuration['ipv4-random'] }}
global-ipv6 = {{ slap_configuration['ipv6-random'] }}

42 43 44 45 46 47 48 49 50 51 52
[directory]
recipe = slapos.cookbook:mkdirectory
etc = ${buildout:directory}/etc
bin = ${buildout:directory}/bin
srv = ${buildout:directory}/srv
var = ${buildout:directory}/var
log = ${:var}/log
scripts = ${:etc}/run
services = ${:etc}/service
novnc-conf = ${:etc}/novnc
run = ${:var}/run
53
prerm = ${:etc}/prerm
54
ca-dir = ${:srv}/ssl
55
public = ${:srv}/public/
56 57 58
cron-entries = ${:etc}/cron.d
crontabs = ${:etc}/crontabs
cronstamps = ${:etc}/cronstamps
59 60 61 62
{%- if boot_image_url_list_enabled %}
boot-image-url-list-repository = ${:srv}/boot-image-url-list-repository
boot-image-url-list-var = ${:var}/boot-image-url-list
boot-image-url-list-expose = ${monitor-directory:private}/boot-image-url-list
63
{%- endif %}
64 65 66 67 68
{%- if boot_image_url_select_enabled %}
boot-image-url-select-repository = ${:srv}/boot-image-url-select-repository
boot-image-url-select-var = ${:var}/boot-image-url-select
boot-image-url-select-expose = ${monitor-directory:private}/boot-image-url-select
{%- endif %}
69 70 71 72 73

[create-mac]
recipe = slapos.cookbook:generate.mac
storage-path = ${directory:srv}/mac

74 75 76 77
[create-tap-mac]
recipe = slapos.cookbook:generate.mac
storage-path = ${directory:srv}/tap_mac

78 79 80 81 82
[gen-passwd]
recipe = slapos.cookbook:generate.password
storage-path = ${directory:srv}/passwd
bytes = 8

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
{% if boot_image_url_select_enabled %}
## boot-image-url-select support BEGIN
[empty-file-state-base-select-promise]
<= monitor-promise-base
module = check_file_state
name = ${:_buildout_section_name_}.py
config-state = empty
# It's very hard to put the username and password correctly, after schema://
# and before the host, as it's not the way how one can use monitor provided
# information, so just show the information in the URL
config-url = ${monitor-base:base-url}/private/boot-image-url-select/${:filename} with username ${monitor-publish-parameters:monitor-user} and password ${monitor-publish-parameters:monitor-password}

[boot-image-url-select-source-config]
recipe = slapos.recipe.template:jinja2
template = inline:
{%- raw %}
  {{ boot_image_url_select }}
{% endraw -%}
101
boot-image-url-select = {{ dumps(slapparameter_dict['boot-image-url-select']) }}
102
context =
103
  key boot_image_url_select :boot-image-url-select
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
rendered = ${directory:etc}/boot-image-url-select.json

[boot-image-url-select-processed-config]
# compares if the current configuration has been used by
# the boot-image-url-select-download, if not, exposes it as not empty file with
# information
recipe = slapos.recipe.build
install =
  import os
  import hashlib
  if not os.path.exists(location):
    os.mkdir(location)
  with open('${:state-file}', 'w') as state_handler:
    try:
      with open('${:config-file}', 'rb') as config_handler, open('${:processed-md5sum}') as processed_handler:
        config_md5sum = hashlib.md5(config_handler.read()).hexdigest()
        processed_md5sum = processed_handler.read()
        if config_md5sum == processed_md5sum:
          state_handler.write('')
        else:
          state_handler.write('config %s != processed %s' % (config_md5sum, processed_md5sum))
    except Exception as e:
      state_handler.write(str(e))

update = ${:install}
config-file = ${boot-image-url-select-source-config:rendered}
state-filename = boot-image-url-select-processed-config.state
state-file = ${directory:boot-image-url-select-expose}/${:state-filename}
processed-md5sum = ${directory:boot-image-url-select-var}/update-image-processed.md5sum

[boot-image-url-select-processed-config-promise]
# promise to check if the configuration provided by the user has been already
# processed by the boot-image-url-select-download script, which runs asynchronously
<= empty-file-state-base-select-promise
filename = ${boot-image-url-select-processed-config:state-filename}
config-filename = ${boot-image-url-select-processed-config:state-file}

[boot-image-url-select-json-config]
# generates json configuration from user configuration
recipe = plone.recipe.command
command = {{ python_executable }} {{ image_download_config_creator }} ${boot-image-url-select-source-config:rendered} ${:rendered} ${directory:boot-image-url-select-repository} ${:error-state-file}
update-command = ${:command}
rendered = ${directory:boot-image-url-select-var}/boot-image-url-select.json
error-state-filename = boot-image-url-select-json-config-error.txt
error-state-file = ${directory:boot-image-url-select-expose}/${:error-state-filename}

[boot-image-url-select-config-state-promise]
# promise to check if configuration has been parsed without errors
<= empty-file-state-base-select-promise
filename = ${boot-image-url-select-json-config:error-state-filename}
config-filename = ${boot-image-url-select-json-config:error-state-file}

[boot-image-url-select-download-wrapper]
# wrapper to execute boot-image-url-select-download on each run
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:scripts}/boot-image-url-select-updater
command-line = {{ python_executable }} {{ image_download_controller }} ${boot-image-url-select-json-config:rendered} {{ curl_executable_location }} ${:md5sum-state-file} ${:error-state-file} ${boot-image-url-select-processed-config:processed-md5sum}
md5sum-state-filename = boot-image-url-select-download-controller-md5sum-fail.json
md5sum-state-file = ${directory:boot-image-url-select-expose}/${:md5sum-state-filename}
error-state-filename = boot-image-url-select-download-controller-error.text
error-state-file = ${directory:boot-image-url-select-expose}/${:error-state-filename}
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg

[boot-image-url-select-download-md5sum-promise]
# promise to report errors with problems with calculating md5sum of the
# downloaded images
<= empty-file-state-base-select-promise
filename = ${boot-image-url-select-download-wrapper:md5sum-state-filename}
config-filename = ${boot-image-url-select-download-wrapper:md5sum-state-file}

[boot-image-url-select-download-state-promise]
# promise to report errors during download
<= empty-file-state-base-select-promise
filename = ${boot-image-url-select-download-wrapper:error-state-filename}
config-filename = ${boot-image-url-select-download-wrapper:error-state-file}
## boot-image-url-select support END
{% endif %} {# if boot_image_url_select_enabled #}

182 183
{% if boot_image_url_list_enabled %}
## boot-image-url-list support BEGIN
184
[empty-file-state-base-list-promise]
185 186 187 188 189 190 191
<= monitor-promise-base
module = check_file_state
name = ${:_buildout_section_name_}.py
config-state = empty
# It's very hard to put the username and password correctly, after schema://
# and before the host, as it's not the way how one can use monitor provided
# information, so just show the information in the URL
192
config-url = ${monitor-base:base-url}/private/boot-image-url-list/${:filename} with username ${monitor-publish-parameters:monitor-user} and password ${monitor-publish-parameters:monitor-password}
193

194
[boot-image-url-list-source-config]
195 196 197
recipe = slapos.recipe.template:jinja2
template = inline:
{%- raw %}
198
  {{ boot_image_url_list }}
199
{% endraw -%}
200
boot-image-url-list = {{ dumps(slapparameter_dict['boot-image-url-list']) }}
201
context =
202
  key boot_image_url_list :boot-image-url-list
203
rendered = ${directory:etc}/boot-image-url-list.conf
204

205
[boot-image-url-list-processed-config]
206
# compares if the current configuration has been used by
207
# the boot-image-url-list-download, if not, exposes it as not empty file with
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
# information
recipe = slapos.recipe.build
install =
  import os
  import hashlib
  if not os.path.exists(location):
    os.mkdir(location)
  with open('${:state-file}', 'w') as state_handler:
    try:
      with open('${:config-file}', 'rb') as config_handler, open('${:processed-md5sum}') as processed_handler:
        config_md5sum = hashlib.md5(config_handler.read()).hexdigest()
        processed_md5sum = processed_handler.read()
        if config_md5sum == processed_md5sum:
          state_handler.write('')
        else:
          state_handler.write('config %s != processed %s' % (config_md5sum, processed_md5sum))
    except Exception as e:
      state_handler.write(str(e))

update = ${:install}
228 229 230 231
config-file = ${boot-image-url-list-source-config:rendered}
state-filename = boot-image-url-list-processed-config.state
state-file = ${directory:boot-image-url-list-expose}/${:state-filename}
processed-md5sum = ${directory:boot-image-url-list-var}/update-image-processed.md5sum
232

233
[boot-image-url-list-processed-config-promise]
234
# promise to check if the configuration provided by the user has been already
235
# processed by the boot-image-url-list-download script, which runs asynchronously
236
<= empty-file-state-base-list-promise
237 238
filename = ${boot-image-url-list-processed-config:state-filename}
config-filename = ${boot-image-url-list-processed-config:state-file}
239

240
[boot-image-url-list-json-config]
241 242
# generates json configuration from user configuration
recipe = plone.recipe.command
243
command = {{ python_executable }} {{ image_download_config_creator }} ${boot-image-url-list-source-config:rendered} ${:rendered} ${directory:boot-image-url-list-repository} ${:error-state-file}
244
update-command = ${:command}
245 246 247
rendered = ${directory:boot-image-url-list-var}/boot-image-url-list.json
error-state-filename = boot-image-url-list-json-config-error.txt
error-state-file = ${directory:boot-image-url-list-expose}/${:error-state-filename}
248

249
[boot-image-url-list-config-state-promise]
250
# promise to check if configuration has been parsed without errors
251
<= empty-file-state-base-list-promise
252 253
filename = ${boot-image-url-list-json-config:error-state-filename}
config-filename = ${boot-image-url-list-json-config:error-state-file}
254

255 256
[boot-image-url-list-download-wrapper]
# wrapper to execute boot-image-url-list-download on each run
257
recipe = slapos.cookbook:wrapper
258 259 260 261 262 263
wrapper-path = ${directory:scripts}/boot-image-url-list-updater
command-line = {{ python_executable }} {{ image_download_controller }} ${boot-image-url-list-json-config:rendered} {{ curl_executable_location }} ${:md5sum-state-file} ${:error-state-file} ${boot-image-url-list-processed-config:processed-md5sum}
md5sum-state-filename = boot-image-url-list-download-controller-md5sum-fail.json
md5sum-state-file = ${directory:boot-image-url-list-expose}/${:md5sum-state-filename}
error-state-filename = boot-image-url-list-download-controller-error.text
error-state-file = ${directory:boot-image-url-list-expose}/${:error-state-filename}
264 265
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg

266
[boot-image-url-list-download-md5sum-promise]
267 268
# promise to report errors with problems with calculating md5sum of the
# downloaded images
269
<= empty-file-state-base-list-promise
270 271
filename = ${boot-image-url-list-download-wrapper:md5sum-state-filename}
config-filename = ${boot-image-url-list-download-wrapper:md5sum-state-file}
272

273
[boot-image-url-list-download-state-promise]
274
# promise to report errors during download
275
<= empty-file-state-base-list-promise
276 277 278 279
filename = ${boot-image-url-list-download-wrapper:error-state-filename}
config-filename = ${boot-image-url-list-download-wrapper:error-state-file}
## boot-image-url-list support END
{% endif %} {# if boot_image_url_list_enabled #}
280

281
[kvm-controller-parameter-dict]
282
python-path = {{ python_eggs_executable }}
283
vnc-passwd = ${gen-passwd:passwd}
284
socket-path = ${directory:var}/qmp_socket
285
pid-file = ${directory:run}/pid_file
286
kvm-status-path = ${directory:var}/qemu-vm-is-ready
287
cpu-count = ${slap-parameter:cpu-count}
288
cpu-model = ${slap-parameter:cpu-model}
289 290 291
ram-hotplug-slot-size = ${slap-parameter:ram-hotplug-slot-size}
ram-size = ${slap-parameter:ram-size}
enable-device-hotplug = ${slap-parameter:enable-device-hotplug}
292

293 294
[kvm-parameter-dict]
python-path = {{ python_executable }}
295 296 297 298 299
ipv4 = ${slap-network-information:local-ipv4}
ipv6 = ${slap-network-information:global-ipv6}
vnc-ip = ${:ipv4}
vnc-port = 5901

300
default-cdrom-iso = {{ debian_amd64_netinst_location }}
301 302
{% if boot_image_url_list_enabled %}
boot-image-url-list-json-config = ${boot-image-url-list-json-config:rendered}
303
{% else %}
304
boot-image-url-list-json-config =
305
{% endif %}
306 307 308 309 310
{% if boot_image_url_select_enabled %}
boot-image-url-select-json-config = ${boot-image-url-select-json-config:rendered}
{% else %}
boot-image-url-select-json-config =
{% endif %}
311 312 313 314 315
nbd-host = ${slap-parameter:nbd-host}
nbd-port = ${slap-parameter:nbd-port}
nbd2-host = ${slap-parameter:nbd2-host}
nbd2-port = ${slap-parameter:nbd2-port}

316
tap-interface = {{ slap_configuration.get('tap-name', '') }}
317
tap-ipv6-addr = {{ slap_configuration.get('tap-ipv6-addr', '') }}
318 319 320

disk-size = ${slap-parameter:disk-size}
disk-type = ${slap-parameter:disk-type}
321
disk-format = ${slap-parameter:disk-format}
322
disk-device-path = ${slap-parameter:disk-device-path}
323
disk-path = ${directory:srv}/virtual.${slap-parameter:disk-format}
324

325
pid-file-path = ${kvm-controller-parameter-dict:pid-file}
326
socket-path = ${kvm-controller-parameter-dict:socket-path}
327

328 329
enable-device-hotplug = ${kvm-controller-parameter-dict:enable-device-hotplug}
smp-count = ${kvm-controller-parameter-dict:cpu-count}
330
smp-max-count = {{ cpu_max_count }}
331 332

ram-size = ${kvm-controller-parameter-dict:ram-size}
333
ram-max-size = {{ ram_max_size }}
334
init-ram-size = 1024
335
mac-address = ${create-mac:mac-address}
336
tap-mac-address = ${create-tap-mac:mac-address}
337 338

use-tap = ${slap-parameter:use-tap}
339
use-nat = ${slap-parameter:use-nat}
340
nat-rules = {{ nat_rule_list }}
341
nat-restrict= {{ dumps(nat_restrict) }}
342
enable-vhost = ${slap-parameter:enable-vhost}
343 344 345

virtual-hard-drive-url = ${slap-parameter:virtual-hard-drive-url}
virtual-hard-drive-md5sum = ${slap-parameter:virtual-hard-drive-md5sum}
346
virtual-hard-drive-gzipped = ${slap-parameter:virtual-hard-drive-gzipped}
347
hard-drive-url-check-certificate = ${slap-parameter:hard-drive-url-check-certificate}
348 349 350 351 352

shell-path = {{ dash_executable_location }}
qemu-path =  {{ qemu_executable_location }}
qemu-img-path = {{ qemu_img_executable_location }}

353
etc-directory = ${directory:etc}
354
disk-storage-list =
355 356 357 358 359
{% for key, path in storage_dict.items() -%}
{{ '  ' ~ key ~ ' ' ~ path }}
{% endfor -%}
external-disk-number = ${slap-parameter:external-disk-number}
external-disk-size = ${slap-parameter:external-disk-size}
360
external-disk-format = ${slap-parameter:external-disk-format}
361

362
{% if enable_http -%}
363 364 365 366
httpd-port = ${slap-parameter:httpd-port}
{% else -%}
httpd-port = 0
{% endif -%}
367 368 369 370 371 372

# Main instance document server info
{% if slapparameter_dict.get('document-host', '') and slapparameter_dict.get('document-port', '') -%}
cluster-doc-host = ${tunnel-cluster-url:ipv4}
cluster-doc-port = ${tunnel-cluster-url:ipv4-port}
{% else -%}
373
cluster-doc-host =
374 375
cluster-doc-port = 0
{% endif -%}
376
netcat-binary = {{ netcat_bin }}
377
language = ${slap-parameter:keyboard-layout-language}
378

379 380 381 382 383
name = {{ slapparameter_dict.get('name', 'Single KVM') }}
disk-cache = ${slap-parameter:disk-cache}
disk-aio = ${slap-parameter:disk-aio}
auto-ballooning = ${slap-parameter:auto-ballooning}
machine-options = ${slap-parameter:machine-options}
384
cpu-model = ${slap-parameter:cpu-model}
385 386 387

log-file = ${directory:log}/qemu.log

388 389 390 391 392
[kvm-run]
recipe = slapos.recipe.template:jinja2
template = {{ template_kvm_run }}
rendered = ${directory:bin}/kvm_raw
mode = 700
393
context =
394 395
  section parameter_dict kvm-parameter-dict

396
[kvm-controller]
397 398
recipe = slapos.recipe.template:jinja2
template = {{ template_kvm_controller_run }}
399
rendered = ${directory:bin}/kvm_controller_raw
400
mode = 700
401
context =
402 403 404 405 406 407 408 409
  section parameter_dict kvm-controller-parameter-dict

[tunnel-6to4-base]
recipe = slapos.cookbook:wrapper
ipv4 = ${slap-network-information:local-ipv4}
ipv6 = ${slap-network-information:global-ipv6}
wrapper-path = ${directory:services}/6tunnel-${:ipv6-port}
command-line = {{ sixtunnel_executable_location }} -6 -4 -d -l ${:ipv6} ${:ipv6-port} ${:ipv4} ${:ipv4-port}
410
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg
411

412
{% if use_nat and nat_rule_list -%}
413
{%   for port in nat_rule_list.split(' ') -%}
414 415 416 417 418
{%     if ':' in port -%}
{%       set proto, port = port.split(':') -%}
{%     else -%}
{%       set proto, port = 'tcp', port -%}
{%     endif -%}
419
{%     set external_port = 10000 + port|int() -%}
420
{%     set section_name = '6tunnel-' ~ proto ~ '-' ~ external_port -%}
421 422 423 424 425 426 427 428 429 430 431 432 433
[{{ section_name }}]
<= tunnel-6to4-base
ipv4-port = {{ external_port }}
ipv6-port = {{ external_port }}
{%     do part_list.append(section_name) -%}
{%   endfor -%}
{% endif -%}

[kvm-instance]
recipe = slapos.cookbook:wrapper
socket-path = ${kvm-controller-parameter-dict:socket-path}
wrapper-path = ${directory:services}/kvm
command-line = ${kvm-run:rendered}
434
kvm-controller = ${kvm-controller-wrapper:wrapper-path}
435
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg
436 437 438 439 440 441


[kvm-controller-wrapper]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:scripts}/kvm_controller
command-line = ${kvm-controller:rendered}
442 443


444
[kvm-vnc-promise]
445 446 447 448 449
<= monitor-promise-base
module = check_port_listening
name = vnc_promise.py
config-hostname = ${kvm-parameter-dict:vnc-ip}
config-port = ${kvm-parameter-dict:vnc-port}
450

451
[kvm-disk-image-corruption-bin]
452 453
recipe = collective.recipe.template
input = inline:#!/bin/sh
454 455 456
  # Return code 0 is "OK"
  # Return code 3 is "found leaks, but image is OK"
  # http://git.qemu.org/?p=qemu.git;a=blob;f=qemu-img.c;h=4e9a7f5741c9cb863d978225829e68fefcae3947;hb=HEAD#l702
457 458 459 460
  if [ "${slap-parameter:disk-device-path}" != "" ]; then
    # disk device option is used, skip qemu img check
    exit 0
  fi
461
  ${kvm-parameter-dict:qemu-img-path} check -U ${kvm-parameter-dict:disk-path} > /dev/null 2>&1
462 463 464 465 466 467
  RETURN_CODE=$?
  if [ $RETURN_CODE -eq 0 ] || [ $RETURN_CODE -eq 3 ]; then
    exit 0
  else
    exit 1
  fi
468
output = ${directory:bin}/kvm-disk-image-corruption
469 470
mode = 700

471 472 473 474 475 476 477
[kvm-disk-image-corruption-promise]
# Check that disk image is not corrupted
<= monitor-promise-base
module = check_command_execute
name = kvm-disk-image-corruption.py
config-command = ${kvm-disk-image-corruption-bin:output}

478
{% if wipe_disk -%}
479 480 481 482 483 484 485 486
{% do part_list.append('wipe-disk-wrapper') -%}
{% set wipe_file_list = '${kvm-parameter-dict:disk-path}' -%}
{% if storage_dict -%}
{% set wipe_file_list = '${kvm-parameter-dict:disk-path}' ~ ' ' ~ '/* '.join(storage_dict.values()) ~ '/*' -%}
{% endif -%}
[wipe-disk-wrapper]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:prerm}/slapos_wipe_qemu_disk
487
command-line =
488 489 490
  {{ wipe_disk_wrapper }} -n {{ slapparameter_dict.get('wipe-disk-iterations', 1) }} -suz --check-pid-file ${kvm-parameter-dict:pid-file-path} --file {{ wipe_file_list }}
{% endif -%}

491
[kvm-started-bin]
492 493
recipe = slapos.recipe.template:jinja2
template = {{ qemu_start_promise_tpl }}
494
rendered = ${directory:bin}/qemu-virtual-machine-is-ready
495
mode = 700
496
context =
497 498 499
  raw dash {{ dash_executable_location }}
  raw qemu_ready_path ${kvm-controller-parameter-dict:kvm-status-path}
  raw qemu_service_log_file ${buildout:directory}/.${slap-connection:partition-id}_kvm.log
500

501 502 503 504 505 506
[kvm-started-promise]
<= monitor-promise-base
module = check_command_execute
name = qemu-virtual-machine-is-ready.py
config-command = ${kvm-started-bin:rendered}

507 508 509 510 511
[novnc-instance]
recipe = slapos.cookbook:novnc
path = ${ca-novnc:executable}
ip = ${slap-network-information:global-ipv6}
port = 6080
512 513
vnc-ip = ${kvm-parameter-dict:vnc-ip}
vnc-port = ${kvm-parameter-dict:vnc-port}
514 515 516 517 518 519 520
novnc-location = {{ novnc_location }}
websockify-path = {{ websockify_executable_location }}
ssl-key-path = ${ca-novnc:key-file}
ssl-cert-path = ${ca-novnc:cert-file}

[websockify-sighandler]
recipe = slapos.cookbook:signalwrapper
521
wrapper-path = ${directory:bin}/websockify-sighandler
522 523
wrapped-path = ${novnc-instance:path}

524 525 526 527
[websockify-sighandler-service]
recipe = slapos.cookbook:wrapper
command-line = ${websockify-sighandler:wrapper-path}
wrapper-path = ${directory:services}/websockify
528
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg
529 530 531
wait-for-files =
  ${ca-novnc:key-file}
  ${ca-novnc:cert-file}
532

533 534 535 536 537
[certificate-authority]
recipe = slapos.cookbook:certificate_authority
openssl-binary = {{ openssl_executable_location }}
ca-dir = ${directory:ca-dir}
requests-directory = ${cadirectory:requests}
538
wrapper = ${directory:bin}/certificate_authority
539 540 541 542 543
ca-private = ${cadirectory:private}
ca-certs = ${cadirectory:certs}
ca-newcerts = ${cadirectory:newcerts}
ca-crl = ${cadirectory:crl}

544 545 546 547
[certificate-authority-service]
recipe = slapos.cookbook:wrapper
command-line = ${certificate-authority:wrapper}
wrapper-path = ${directory:services}/certificate_authority
548
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg
549

550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
[cadirectory]
recipe = slapos.cookbook:mkdirectory
requests = ${directory:ca-dir}/requests/
private = ${directory:ca-dir}/private/
certs = ${directory:ca-dir}/certs/
newcerts = ${directory:ca-dir}/newcerts/
crl = ${directory:ca-dir}/crl/

[ca-novnc]
<= certificate-authority
recipe = slapos.cookbook:certificate_authority.request
key-file = ${directory:novnc-conf}/novnc.key
cert-file = ${directory:novnc-conf}/novnc.crt
executable = ${directory:bin}/novnc
wrapper = ${directory:bin}/websockify

[novnc-promise]
567 568 569 570 571
<= monitor-promise-base
module = check_port_listening
name = novnc_promise.py
config-hostname = ${novnc-instance:ip}
config-port = ${novnc-instance:port}
572 573 574 575 576 577 578 579 580 581 582 583 584


#----------------
#--
#-- Deploy cron.

[cron]
recipe = slapos.cookbook:cron
dcrond-binary = {{ dcron_executable_location }}
cron-entries = ${directory:cron-entries}
crontabs = ${directory:crontabs}
cronstamps = ${directory:cronstamps}
catcher = ${cron-simplelogger:wrapper}
585 586 587 588 589 590
binary = ${directory:bin}/crond_raw

[cron-service]
recipe = slapos.cookbook:wrapper
command-line = ${cron:binary}
wrapper-path = ${directory:services}/crond
591
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg
592 593 594 595 596 597 598 599 600 601

[cron-simplelogger]
recipe = slapos.cookbook:simplelogger
wrapper = ${directory:bin}/cron_simplelogger
log = ${directory:log}/crond.log

#----------------
#--
#-- Deploy frontend.

602
[request-slave-frontend-base]
603 604 605 606 607 608 609
recipe = slapos.cookbook:requestoptional
server-url = ${slap-connection:server-url}
key-file = ${slap-connection:key-file}
cert-file = ${slap-connection:cert-file}
computer-id = ${slap-connection:computer-id}
partition-id = ${slap-connection:partition-id}
slave = true
610 611 612 613 614 615 616 617 618 619
config-https-only = True
config-type = websocket
config-url = https://[${novnc-instance:ip}]:${novnc-instance:port}
return = secure_access domain

[request-slave-frontend]
<= request-slave-frontend-base
software-url = ${slap-parameter:frontend-software-url}
software-type = ${slap-parameter:frontend-software-type}
name = ${slap-parameter:frontend-instance-name}
620 621 622
sla-instance_guid = ${slap-parameter:frontend-instance-guid}

[frontend-promise]
623 624 625 626
<= monitor-promise-base
module = check_url_available
name = frontend_promise.py
config-url = ${publish-connection-information:url}
627

628 629 630 631 632 633 634 635 636
{% if additional_frontend %}
[request-slave-frontend-additional]
<= request-slave-frontend-base
software-url = ${slap-parameter:frontend-additional-software-url}
software-type = ${slap-parameter:frontend-additional-software-type}
name = ${slap-parameter:frontend-additional-instance-name}
sla-instance_guid = ${slap-parameter:frontend-additional-instance-guid}

[frontend-additional-promise]
637 638 639 640
<= monitor-promise-base
module = check_url_available
name = frontend_additional_promise.py
config-url = ${publish-connection-information:url-additional}
641
{% endif %}
642

643
{% if enable_http %}
644 645 646 647 648
[httpd]
recipe = slapos.cookbook:simplehttpserver
host = ${slap-network-information:local-ipv4}
port = ${slap-parameter:httpd-port}
base-path = ${directory:public}
649
wrapper = ${directory:bin}/http-server
650 651 652
log-file = ${directory:log}/httpd.log
use-hash-url = false

653 654 655 656
[httpd-service]
recipe = slapos.cookbook:wrapper
command-line = ${httpd:wrapper}
wrapper-path = ${directory:services}/http-server
657
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg
658

659
[httpd-promise]
660 661 662 663 664
<= monitor-promise-base
module = check_port_listening
name = httpd.py
config-hostname = ${httpd:host}
config-port = ${httpd:port}
665 666
{% endif %}

667 668 669
[monitor-instance-parameter]
monitor-httpd-port = 8026
monitor-title = {{ slapparameter_dict.get('name', 'KVM Standalone') }}
670
cors-domains = {{ slapparameter_dict.get('monitor-cors-domains', 'monitor.app.officejs.com') }}
671
{% if slapparameter_dict.get('monitor-username', '') -%}
672
username = {{ slapparameter_dict['monitor-username'] }}
673 674
{% endif -%}
{% if slapparameter_dict.get('monitor-password', '') -%}
675
password = {{ slapparameter_dict['monitor-password'] }}
Alain Takoudjou's avatar
Alain Takoudjou committed
676
{% endif -%}
677
interface-url = {{ slapparameter_dict.get('monitor-interface-url', 'https://monitor.app.officejs.com') }}
Alain Takoudjou's avatar
Alain Takoudjou committed
678

679 680 681 682
# this helper just gives a blank line to insert in multiline values
[helper]
blank-line =

683
[publish-connection-information]
684
<= monitor-publish
685
recipe = slapos.cookbook:publish
Alain Takoudjou's avatar
Alain Takoudjou committed
686
ipv6 = ${slap-network-information:global-ipv6}
687 688
backend-url = https://[${novnc-instance:ip}]:${novnc-instance:port}/vnc.html?auto=1&encrypt=1&password=${kvm-controller-parameter-dict:vnc-passwd}
url = ${request-slave-frontend:connection-secure_access}/vnc.html?auto=1&encrypt=1&password=${kvm-controller-parameter-dict:vnc-passwd}
689
{% if additional_frontend %}
690
url-additional = ${request-slave-frontend-additional:connection-secure_access}/vnc.html?auto=1&encrypt=1&password=${kvm-controller-parameter-dict:vnc-passwd}
691
{% endif %}
692 693
{% set disk_number = len(storage_dict) -%}
maximum-extra-disk-amount = {{ disk_number }}
694
{% set iface = 'ens3' -%}
695
{% if use_nat -%}
696
{%   set iface = 'ens4' -%}
697
{%   if nat_rule_list -%}
698
# Publish NAT port mapping status
699
{%     for port in nat_rule_list.split(' ') -%}
700 701 702 703 704
{%       if ':' in port -%}
{%         set proto, port = port.split(':') -%}
{%       else -%}
{%         set proto, port = 'tcp', port -%}
{%       endif -%}
705
{%       set external_port = 10000 + port|int() -%}
706
nat-rule-port-{{proto}}-{{port}} = ${slap-network-information:global-ipv6} : ${6tunnel-{{proto}}-{{external_port}}:ipv6-port}
707
{%       if slapparameter_dict.get('publish-nat-url', False) -%}
Thomas Gambier's avatar
Thomas Gambier committed
708
nat-rule-url-{{proto}}-{{port}} = [${slap-network-information:global-ipv6}]:${6tunnel-{{proto}}-{{external_port}}:ipv6-port}
709 710 711
{%       endif -%}
{%     endfor -%}
{%   endif -%}
712
{% endif -%}
713
{% if use_tap -%}
714 715
tap-ipv4 = {{ slap_configuration.get('tap-ipv4-addr', '') }}
tap-ipv6 = {{ slap_configuration.get('tap-ipv6-addr', '') }}
716
{% endif -%}
717 718

{% set kvm_http = 'http://${slap-network-information:local-ipv4}:' ~ slapparameter_dict.get('httpd-port', 8081) -%}
719 720
{% if enable_http %}
{%   if use_nat -%}
721 722
{%     set kvm_http = 'http://10.0.2.100' -%}
{%   endif %}
Alain Takoudjou's avatar
Alain Takoudjou committed
723
{%   if slapparameter_dict.get('authorized-key', '') and slapparameter_dict.get('type', '') == 'cluster' -%}
724
key_info = Get the publick key file in your VM with the command: wget {{ kvm_http }}/authorized_keys
725 726 727
{%   endif %}
{% endif %}

728
ipv6-network-info =
729
{% if use_tap and slap_configuration.get('tap-ipv6-addr') %}
730
  PERMANENT SOLUTION: in your VM, add the lines below in /etc/network/interfaces and then run: "ifup {{ iface }}"
731 732 733 734 735
  auto {{ iface }}
  iface {{ iface }} inet6 static
  	address {{ slap_configuration.get('tap-ipv6-gateway') }}
  	netmask {{ slap_configuration.get('tap-ipv6-network').split('/')[1] }}
  	gateway {{ slap_configuration.get('tap-ipv6-addr') }}
736
{% if enable_http %}
737
  ${helper:blank-line}
738 739
  TEMPORARY SOLUTION: run in your VM the command: "wget -O- {{ kvm_http }}/${network-config-ipv6:filename} | /bin/sh -"
  (the configuration will be gone after the next reboot)
740 741 742 743
{% endif %}
{% endif %}


744
{% if use_tap and slap_configuration.get('tap-ipv4-addr') -%}
745
[network-config-ipv4]
746
recipe = plone.recipe.command
747 748
filename = netconfig.sh
path = ${directory:public}/${:filename}
749
ipv4-add-address = ip -4 address add {{ slap_configuration.get('tap-ipv4-addr') }}/{{ slap_configuration.get('tap-ipv4-netmask') }} dev \$IFACE noprefixroute
750
ipv4-add-gateway-route = ip route add {{ slap_configuration.get('tap-ipv4-gateway') }} dev \$IFACE
751
{%   if nat_restrict -%}
752
ipv4-add-default-route = ip route add default via {{ slap_configuration.get('tap-ipv4-gateway') }} dev \$IFACE
753
{%   elif global_ipv4_prefix -%}
754
ipv4-add-default-route = ip route add {{ global_ipv4_prefix }} via {{ slap_configuration.get('tap-ipv4-gateway') }} dev \$IFACE src {{ slap_configuration.get('tap-ipv4-addr') }}
755
{%   else -%}
756
ipv4-add-default-route =
757
{%   endif -%}
758
ipv4-set-link-up = ip link set dev \$IFACE up
759
command =
760 761 762 763
  cat > ${:path} << EOF
  #!/bin/sh
  IFACE={{ iface }}
  #try to be compatible with OS with old names
764 765
  ip a | grep eth0: && [ \$IFACE = ens3 ] && IFACE=eth0
  ip a | grep eth1: && [ \$IFACE = ens4 ] && IFACE=eth1
766
  ${:ipv4-add-address}
767
  ${:ipv4-add-gateway-route}
768 769
  ${:ipv4-add-default-route}
  ${:ipv4-set-link-up}
770 771 772 773
  EOF
update-command = ${:command}
{% endif -%}

774
{% if use_tap and slap_configuration.get('tap-ipv6-addr') -%}
775 776
[network-config-ipv6]
recipe = plone.recipe.command
777 778 779
filename = ipv6_config.sh
path = ${directory:public}/${:filename}
ipv6-add-address = ip -6 address add {{ slap_configuration.get('tap-ipv6-gateway') }}/{{ slap_configuration.get('tap-ipv6-network').split('/')[1] }} dev \$IFACE
780
ipv6-add-default-route =
781 782
  ip -6 route del default ; ip -6 route add default dev \$IFACE via {{ slap_configuration.get('tap-ipv6-addr') }}
ipv6-set-link-up = ip link set dev \$IFACE up
783 784 785 786 787 788
command =
  cat > ${:path} << EOF
  #!/bin/sh
  IFACE={{ iface }}
  ${:ipv6-add-address}
  ${:ipv6-add-default-route}
789
  ${:ipv6-set-link-up}
790
  EOF
791
update-command = ${:command}
792
{% endif -%}
793

794 795 796 797 798 799 800 801 802 803 804 805 806
{% macro writefile(section_name, file_path, content, mode='') -%}
{% set data_list =  content.split('\n') -%}
[{{ section_name }}]
recipe = collective.recipe.template
input = inline:
  {{ data_list | join('\n  ') }}
output = {{ file_path }}
mode = {{ mode }}
{% endmacro -%}

# write vm-data into file public/data
{{ writefile('vm-data-content', '${directory:public}/data', slapparameter_dict.get('data-to-vm', ''), '700') }}

807
{% if slapparameter_dict.get('authorized-key', '') -%}
808
# write public key for vms to public/authorized_keys
809 810
{{   writefile('get-authorized-key', '${directory:public}/authorized_keys', slapparameter_dict.get('authorized-key', ''), '700') }}
{% endif -%}
811

812
{% if use_tap and nat_restrict -%}
813 814 815 816 817
# Ask to set default to tap interface in the vm
{{ writefile('set-default-interface', '${directory:public}/delDefaultIface', iface, '600') }}
{% do part_list.append('set-default-interface') -%}
{% endif -%}

818 819 820
[publish-host-config]
recipe = plone.recipe.command
name = {{ slapparameter_dict.get('name', 'localhost') }}
821
{% if use_tap and slap_configuration.get('tap-ipv4-addr') -%}
822
local-ipv4 = {{ slap_configuration['tap-ipv4-addr'] }}
823 824 825
gateway = {{ slap_configuration.get('tap-ipv4-gateway') }}
netmask = {{ slap_configuration.get('tap-ipv4-network') }}
network = {{ slap_configuration.get('tap-ipv4-netmask') }}
826 827
{% else -%}
local-ipv4 = 127.0.0.1
828 829 830
gateway =
netmask =
network =
831 832 833
{% endif -%}
path-host = ${directory:public}/hostname
path-ip = ${directory:public}/ipv4
834 835 836
path-gateway = ${directory:public}/gateway
path-network = ${directory:public}/network
path-netmask = ${directory:public}/netmask
837
command =
838 839
  rm -f ${:path-host}
  rm -f ${:path-ip}
840 841 842
  rm -f ${:path-gateway}
  rm -f ${:path-network}
  rm -f ${:path-netmask}
843 844
  echo "${:name}" > ${:path-host}
  echo "${:local-ipv4}" > ${:path-ip}
845 846 847
  echo "${:gateway}" > ${:path-gateway}
  echo "${:network}" > ${:path-network}
  echo "${:netmask}" > ${:path-netmask}
848 849
update-command = ${:command}

850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869
# To access documents of main instance (in case of kvm-cluster) through http
[cluster-url-path]
recipe = slapos.recipe.template:jinja2
template = {{ template_content }}
filename = cluster.hash
rendered = ${directory:public}/${:filename}
hash-url = https://10.0.2.101:443/{{ slapparameter_dict.get('document-path', '') }}
context =
    key content_list :hash-url
    raw sep #

# This 6to4 tunnel help to access document url in ipv4
[tunnel-cluster-url]
recipe = slapos.cookbook:ipv4toipv6
ipv6 = {{ slapparameter_dict.get('document-host', '') }}
ipv4 = ${slap-network-information:local-ipv4}
ipv6-port = {{ slapparameter_dict.get('document-port', '') }}
ipv4-port = 16936
shell-path = {{ dash_executable_location }}
6tunnel-path = {{ sixtunnel_executable_location }}
870 871 872 873 874 875
runner-path = ${directory:bin}/6tunnel-cluster

[tunnel-cluster-service]
recipe = slapos.cookbook:wrapper
command-line = ${tunnel-cluster-url:runner-path}
wrapper-path = ${directory:services}/6tunnel-cluster
876
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg
877

878
[ansible-vm-bin]
879 880
recipe = slapos.recipe.template:jinja2
template = {{ ansible_promise_tpl }}
881
rendered = ${directory:bin}/ansible_{{ name }}
882 883 884 885 886
extensions = jinja2.ext.do
context =
  raw logs ${directory:public}/ansible
  raw name {{ name }}

887 888
[ansible-vm-promise]
<= monitor-promise-base
889
module = check_command_execute
890 891 892
name = ansible_{{ name }}.py
config-command = ${ansible-vm-bin:rendered}

893
{% if bootstrap_script_url -%}
894
[download-bootstrap-script]
895 896 897 898 899 900 901 902 903 904
recipe = slapos.recipe.build
location = ${directory:public}/vm-bootstrap
install =
  from zc.buildout.download import check_md5sum, urlretrieve, ChecksumError
  url, md5sum = {{ repr(bootstrap_script_url) }}.split('#')
  urlretrieve(url, location)
  if not check_md5sum(location, md5sum):
    os.remove(location)
    raise ChecksumError
{% endif -%}
905

906 907 908 909 910
[logrotate-vm-bootstrap]
< = logrotate-entry-base
name = vm-bootstrap
log = ${directory:public}/ansible/vm-bootstrap.log

911 912
[slap-parameter]
# Default values if not specified
913 914
frontend-software-type = RootSoftwareInstance
frontend-software-url = http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg
915
frontend-instance-guid =
916 917 918 919 920
frontend-instance-name = VNC Real Frontend
frontend-additional-software-type = RootSoftwareInstance
frontend-additional-software-url = http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg
frontend-additional-instance-guid =
frontend-additional-instance-name = VNC Real Frontend Additional
921 922 923 924
nbd-port = 1024
nbd-host =
nbd2-port = 1024
nbd2-host =
925
boot-image-url-list =
926

927
enable-device-hotplug = False
928
ram-size = 1024
929
ram-hotplug-slot-size = 512
930 931
disk-size = 10
disk-type = virtio
932 933
disk-format = qcow2
disk-device-path =
934 935

cpu-count = 1
936 937 938
disk-cache = writeback
disk-aio = native
auto-ballooning = True
939
machine-options =
940
cpu-model = host
941 942

nat-rules = 22 80 443
943
use-nat = True
944
use-tap = True
945
nat-restrict-mode = False
946
enable-vhost = False
947 948 949

virtual-hard-drive-url =
virtual-hard-drive-md5sum =
950
virtual-hard-drive-gzipped = False
951 952
# if virtual-hard-drive-url use https, then specify if https certificate should be checked or not
hard-drive-url-check-certificate = True
953 954 955

external-disk-number = 0
external-disk-size = 20
956
external-disk-format = qcow2
957

958
# Help to get some configuration files into the vm from http
959 960
enable-http-server = False
httpd-port = 8081
961
# for auto config, the public key file will be available in the VM via url http://10.0.2.100/authorized_key if use-nat = True
962
authorized-key =
963 964 965

# send some content which will be accessible to the vm through static url: http://10.0.2.100/data
data-to-vm =
966

967 968
# Change keyboard layout language (Change to en-us if you face some bad bihaviors)
keyboard-layout-language = fr
969

970
{% for k, v in slapparameter_dict.items() -%}
971 972 973 974
{% if k == 'authorized-key' and v -%}
{% set key_list =  v.split('\n') -%}
{{ k }} =
  {{ key_list | join('\n  ') }}
975
{% elif k in ['boot-image-url-list', 'boot-image-url-select', 'whitelist-domains'] %}
976 977
{# needs to decorate possibly multiline or maybe unsafe value #}
{{ k }} = {{ dumps(v) }}
978
{% else -%}
979
{{ k }} = {{ v }}
980
{% endif -%}
981 982
{% endfor -%}

983 984 985 986 987 988 989
#############################
#
# Instanciate kvm (Buildout Section)
#
#############################

{% if slapparameter_dict.get('document-host', '') %}
990
# Set Additionals parts
991 992
{%   do part_list.append('cluster-url-path') -%}
{% endif -%}
993
{% if enable_http %}
994
{%   do part_list.extend(['httpd', 'httpd-service', 'httpd-promise', 'publish-host-config']) -%}
995 996 997
{% if slapparameter_dict.get('data-to-vm', '') %}
{%   do part_list.append('vm-data-content') -%}
{% endif -%}
998
{% if not disable_ansible_promise %}
999 1000
{%   do part_list.extend(['ansible-vm-promise', 'logrotate-vm-bootstrap']) -%}
{% endif -%}
Alain Takoudjou's avatar
Alain Takoudjou committed
1001
{% if slapparameter_dict.get('authorized-key', '') and slapparameter_dict.get('type', '') == 'cluster' %}
1002
{%   do part_list.append('get-authorized-key') -%}
1003
{% endif -%}
1004
{% if bootstrap_script_url -%}
1005 1006
{%   do part_list.append('download-bootstrap-script') -%}
{% endif -%}
1007 1008 1009
{% if slapparameter_dict.get('document-port', '') -%}
{%   do part_list.append('tunnel-cluster-service') -%}
{% endif -%}
1010 1011 1012 1013

{% endif -%}


1014 1015 1016 1017 1018 1019
{% if disk_device_path %}
{%   do part_list.append('disk-device-permission') -%}
[disk-device-permission]
recipe = slapos.recipe.template:jinja2
template = inline:
{%- raw %}
1020 1021 1022 1023 1024
  {%- set disk_list = [] %}
  {%- for disk in disk_device_path.split() %}
  {%-   do disk_list.append({'disk': disk}) %}
  {%- endfor -%}
  {{ json_module.dumps(disk_list) }}
1025 1026
{% endraw -%}
rendered = ${buildout:directory}/.slapos-disk-permission
1027
extensions = jinja2.ext.do
1028
context =
1029
  import json_module json
1030
  raw disk_device_path {{disk_device_path}}
1031 1032 1033

{%   do part_list.append('wipe-disk-device-wrapper') -%}
[wipe-disk-device-wrapper]
1034 1035 1036 1037 1038 1039 1040
recipe = slapos.recipe.template:jinja2
template = inline:
{%- for disk_device in disk_device_path.split() %}
  dd if=/dev/zero of={{ disk_device }} bs=4096 count=500k
{%- endfor %}
rendered = ${directory:prerm}/slapos_wipe_device_disk
mode = 0700
1041 1042
{% endif -%}

1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
{%   do part_list.append('whitelist-firewall') -%}
[whitelist-firewall]
recipe = slapos.cookbook:wrapper
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg
wrapper-path = ${directory:scripts}/${:_buildout_section_name_}
command-line =
  {{ dnsresolver_executable }}
  --style list
  --output ${:output}
  ${:source}

source =
  ${whitelist-domains-request:rendered}
  {{ whitelist_domains_default }}
  ${whitelist-domains-resolv.conf:output}
  ${whitelist-domains-download:output}
output = ${buildout:directory}/.slapos-whitelist-firewall

[whitelist-firewall-directory]
recipe = plone.recipe.command
location = ${buildout:parts-directory}/whitelist-firewall
command = mkdir -p ${:location}
update-command = ${:command}

[whitelist-domains-request]
recipe = slapos.recipe.template:jinja2
template = inline:
{%- raw %}
  {%- for domain in whitelist_domains.split() %}
  {{ domain }}
  {%- endfor %}
{% endraw -%}
rendered = ${whitelist-firewall-directory:location}/${:_buildout_section_name_}.txt
whitelist-domains = {{ dumps(whitelist_domains) }}
extensions = jinja2.ext.do
context =
  key whitelist_domains :whitelist-domains

[whitelist-domains-resolv.conf]
recipe = plone.recipe.command
output = ${whitelist-firewall-directory:location}/${:_buildout_section_name_}.txt
update-command = ${:command}
command =
  egrep ^nameserver /etc/resolv.conf  | cut -d ' ' -f 2 > ${:output}

[whitelist-domains-download]
recipe = slapos.cookbook:wrapper
hash-existing-files = ${buildout:directory}/software_release/buildout.cfg
wrapper-path = ${directory:scripts}/${:_buildout_section_name_}
output = ${whitelist-firewall-directory:location}/${:_buildout_section_name_}.txt
interval = 3600
command-line = {{ python_executable }} {{ whitelist_firewall_download_controller }} {{ curl_executable_location }} 3600 ${:output} ${:url}

url = https://stream.nxdcdn.com/rapidspace-whitelist-domains

1098
[instance-kvm-parts]
1099 1100
parts =
  certificate-authority
1101
  certificate-authority-service
1102 1103
  publish-connection-information
  kvm-instance
1104
  kvm-controller-wrapper
1105 1106 1107
  kvm-vnc-promise
  kvm-disk-image-corruption-promise
  websockify-sighandler
1108
  websockify-sighandler-service
1109
  novnc-promise
1110
  kvm-started-promise
1111
  cron
1112
  cron-service
1113
  cron-entry-logrotate
1114
  frontend-promise
1115 1116 1117 1118 1119 1120
{% if boot_image_url_list_enabled %}
  boot-image-url-list-download-wrapper
  boot-image-url-list-config-state-promise
  boot-image-url-list-download-md5sum-promise
  boot-image-url-list-download-state-promise
  boot-image-url-list-processed-config-promise
1121
{% endif %}
1122 1123 1124 1125 1126 1127 1128
{% if boot_image_url_select_enabled %}
  boot-image-url-select-download-wrapper
  boot-image-url-select-config-state-promise
  boot-image-url-select-download-md5sum-promise
  boot-image-url-select-download-state-promise
  boot-image-url-select-processed-config-promise
{% endif %}
1129 1130 1131
{% if additional_frontend %}
  frontend-additional-promise
{% endif %}
1132
# monitor parts
1133
  monitor-base
1134 1135 1136
# Complete parts with sections
  {{ part_list | join('\n  ') }}

1137 1138 1139
[buildout]
parts = ${instance-kvm-parts:parts}

1140
extends =
1141 1142 1143 1144 1145 1146
#  Add extends list
 {{ extends_list | join('\n  ') }}
#  {{ template_httpd_cfg }}

eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
1147
offline = true