{% set additional_frontend = (slapparameter_dict.get('frontend-additional-instance-guid', '').strip() != '') %} {% set enable_http = slapparameter_dict.get('enable-http-server', 'False').lower() -%} {% set use_tap = slapparameter_dict.get('use-tap', 'True').lower() -%} {% set use_nat = slapparameter_dict.get('use-nat', 'True').lower() -%} {% set wipe_disk = slapparameter_dict.get('wipe-disk-ondestroy', 'False').lower() -%} {% set nat_restrict = slapparameter_dict.get('nat-restrict-mode', 'False').lower() -%} {% set name = slapparameter_dict.get('name', 'localhost') -%} {% set disable_ansible_promise = slapparameter_dict.get('disable-ansible-promise', 'True').lower() -%} {% set enable_device_hotplug = slapparameter_dict.get('enable-device-hotplug', 'false').lower() -%} {% set instance_type = slapparameter_dict.get('type', 'standalone') -%} {% set nat_rule_list = slapparameter_dict.get('nat-rules', '22 80 443') -%} {% set disk_device_path = slapparameter_dict.get('disk-device-path', None) -%} {% set extends_list = [] -%} {% set part_list = [] -%} {% set bootstrap_url = '' -%} {% set bootstrap_url_md5sum = '' -%} {% if slapparameter_dict.get('bootstrap-script-url', '') -%} {% set url_info_list = slapparameter_dict['bootstrap-script-url'].split('#') -%} {% set bootstrap_url = url_info_list[0] -%} {% set bootstrap_url_md5sum = url_info_list[1] -%} {% endif -%} {% 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 -%} {% do extends_list.append(template_monitor) -%} {% do extends_list.append(logrotate_cfg) -%} [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 prerm = ${:etc}/prerm ca-dir = ${:srv}/ssl public = ${:srv}/public/ cron-entries = ${:etc}/cron.d crontabs = ${:etc}/crontabs cronstamps = ${:etc}/cronstamps [create-mac] recipe = slapos.cookbook:generate.mac storage-path = ${directory:srv}/mac [create-tap-mac] recipe = slapos.cookbook:generate.mac storage-path = ${directory:srv}/tap_mac [gen-passwd] recipe = slapos.cookbook:generate.password storage-path = ${directory:srv}/passwd bytes = 8 [kvm-controller-parameter-dict] python-path = {{ python_eggs_executable }} vnc-passwd = ${gen-passwd:passwd} socket-path = ${directory:var}/qmp_socket pid-file = ${directory:run}/pid_file kvm-status-path = ${directory:var}/qemu-vm-is-ready cpu-count = ${slap-parameter:cpu-count} cpu-model = ${slap-parameter:cpu-model} ram-hotplug-slot-size = ${slap-parameter:ram-hotplug-slot-size} ram-size = ${slap-parameter:ram-size} enable-device-hotplug = ${slap-parameter:enable-device-hotplug} [kvm-parameter-dict] python-path = {{ python_executable }} ipv4 = ${slap-network-information:local-ipv4} ipv6 = ${slap-network-information:global-ipv6} vnc-ip = ${:ipv4} vnc-port = 5901 default-cdrom-iso = {{ debian_amd64_netinst_location }} nbd-host = ${slap-parameter:nbd-host} nbd-port = ${slap-parameter:nbd-port} nbd2-host = ${slap-parameter:nbd2-host} nbd2-port = ${slap-parameter:nbd2-port} tap-interface = {{ slap_configuration.get('tap-name', '') }} disk-size = ${slap-parameter:disk-size} disk-type = ${slap-parameter:disk-type} disk-format = ${slap-parameter:disk-format} disk-device-path = ${slap-parameter:disk-device-path} disk-path = ${directory:srv}/virtual.${slap-parameter:disk-format} pid-file-path = ${kvm-controller-parameter-dict:pid-file} socket-path = ${kvm-controller-parameter-dict:socket-path} enable-device-hotplug = ${kvm-controller-parameter-dict:enable-device-hotplug} smp-count = ${kvm-controller-parameter-dict:cpu-count} smp-max-count = ${slap-parameter:cpu-max-count} ram-size = ${kvm-controller-parameter-dict:ram-size} ram-max-size = ${slap-parameter:ram-max-size} init-ram-size = 1024 mac-address = ${create-mac:mac-address} tap-mac-address = ${create-tap-mac:mac-address} use-tap = ${slap-parameter:use-tap} use-nat = ${slap-parameter:use-nat} nat-rules = {{ nat_rule_list }} nat-restrict= {{ nat_restrict }} enable-vhost = ${slap-parameter:enable-vhost} virtual-hard-drive-url = ${slap-parameter:virtual-hard-drive-url} virtual-hard-drive-md5sum = ${slap-parameter:virtual-hard-drive-md5sum} virtual-hard-drive-gzipped = ${slap-parameter:virtual-hard-drive-gzipped} hard-drive-url-check-certificate = ${slap-parameter:hard-drive-url-check-certificate} shell-path = {{ dash_executable_location }} qemu-path = {{ qemu_executable_location }} qemu-img-path = {{ qemu_img_executable_location }} etc-directory = ${directory:etc} disk-storage-list = {% 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} external-disk-format = ${slap-parameter:external-disk-format} {% if enable_http == 'true' -%} httpd-port = ${slap-parameter:httpd-port} {% else -%} httpd-port = 0 {% endif -%} # 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 -%} cluster-doc-host = cluster-doc-port = 0 {% endif -%} netcat-binary = {{ netcat_bin }} language = ${slap-parameter:keyboard-layout-language} 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} cpu-model = ${slap-parameter:cpu-model} log-file = ${directory:log}/qemu.log [kvm-run] recipe = slapos.recipe.template:jinja2 template = {{ template_kvm_run }} rendered = ${directory:bin}/kvm_raw mode = 700 context = section parameter_dict kvm-parameter-dict [kvm-controller] recipe = slapos.recipe.template:jinja2 template = {{ template_kvm_controller_run }} rendered = ${directory:bin}/kvm_controller_raw mode = 700 context = 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} hash-existing-files = ${buildout:directory}/software_release/buildout.cfg {% if use_nat == 'true' and nat_rule_list -%} {% for port in nat_rule_list.split(' ') -%} {% if ':' in port -%} {% set proto, port = port.split(':') -%} {% else -%} {% set proto, port = 'tcp', port -%} {% endif -%} {% set external_port = 10000 + port|int() -%} {% set section_name = '6tunnel-' ~ proto ~ '-' ~ external_port -%} [{{ 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} kvm-controller = ${kvm-controller-wrapper:wrapper-path} hash-existing-files = ${buildout:directory}/software_release/buildout.cfg [kvm-controller-wrapper] recipe = slapos.cookbook:wrapper wrapper-path = ${directory:scripts}/kvm_controller command-line = ${kvm-controller:rendered} [kvm-vnc-promise] <= 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} [kvm-disk-image-corruption-bin] recipe = collective.recipe.template input = inline:#!/bin/sh # 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 if [ "${slap-parameter:disk-device-path}" != "" ]; then # disk device option is used, skip qemu img check exit 0 fi ${kvm-parameter-dict:qemu-img-path} check -U ${kvm-parameter-dict:disk-path} > /dev/null 2>&1 RETURN_CODE=$? if [ $RETURN_CODE -eq 0 ] || [ $RETURN_CODE -eq 3 ]; then exit 0 else exit 1 fi output = ${directory:bin}/kvm-disk-image-corruption mode = 700 [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} {% if wipe_disk == 'true' -%} {% 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 command-line = {{ 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 -%} [kvm-started-bin] recipe = slapos.recipe.template:jinja2 template = {{ qemu_start_promise_tpl }} rendered = ${directory:bin}/qemu-virtual-machine-is-ready mode = 700 context = 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 [kvm-started-promise] <= monitor-promise-base module = check_command_execute name = qemu-virtual-machine-is-ready.py config-command = ${kvm-started-bin:rendered} [novnc-instance] recipe = slapos.cookbook:novnc path = ${ca-novnc:executable} ip = ${slap-network-information:global-ipv6} port = 6080 vnc-ip = ${kvm-parameter-dict:vnc-ip} vnc-port = ${kvm-parameter-dict:vnc-port} 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 wrapper-path = ${directory:bin}/websockify-sighandler wrapped-path = ${novnc-instance:path} [websockify-sighandler-service] recipe = slapos.cookbook:wrapper command-line = ${websockify-sighandler:wrapper-path} wrapper-path = ${directory:services}/websockify hash-existing-files = ${buildout:directory}/software_release/buildout.cfg wait-for-files = ${ca-novnc:key-file} ${ca-novnc:cert-file} [certificate-authority] recipe = slapos.cookbook:certificate_authority openssl-binary = {{ openssl_executable_location }} ca-dir = ${directory:ca-dir} requests-directory = ${cadirectory:requests} wrapper = ${directory:bin}/certificate_authority ca-private = ${cadirectory:private} ca-certs = ${cadirectory:certs} ca-newcerts = ${cadirectory:newcerts} ca-crl = ${cadirectory:crl} [certificate-authority-service] recipe = slapos.cookbook:wrapper command-line = ${certificate-authority:wrapper} wrapper-path = ${directory:services}/certificate_authority hash-existing-files = ${buildout:directory}/software_release/buildout.cfg [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] <= monitor-promise-base module = check_port_listening name = novnc_promise.py config-hostname = ${novnc-instance:ip} config-port = ${novnc-instance:port} #---------------- #-- #-- 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} binary = ${directory:bin}/crond_raw [cron-service] recipe = slapos.cookbook:wrapper command-line = ${cron:binary} wrapper-path = ${directory:services}/crond hash-existing-files = ${buildout:directory}/software_release/buildout.cfg [cron-simplelogger] recipe = slapos.cookbook:simplelogger wrapper = ${directory:bin}/cron_simplelogger log = ${directory:log}/crond.log #---------------- #-- #-- Deploy frontend. [request-slave-frontend-base] 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 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} sla-instance_guid = ${slap-parameter:frontend-instance-guid} [frontend-promise] <= monitor-promise-base module = check_url_available name = frontend_promise.py config-url = ${publish-connection-information:url} {% 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] <= monitor-promise-base module = check_url_available name = frontend_additional_promise.py config-url = ${publish-connection-information:url-additional} {% endif %} {% if enable_http == 'true' %} [httpd] recipe = slapos.cookbook:simplehttpserver host = ${slap-network-information:local-ipv4} port = ${slap-parameter:httpd-port} base-path = ${directory:public} wrapper = ${directory:bin}/http-server log-file = ${directory:log}/httpd.log use-hash-url = false [httpd-service] recipe = slapos.cookbook:wrapper command-line = ${httpd:wrapper} wrapper-path = ${directory:services}/http-server hash-existing-files = ${buildout:directory}/software_release/buildout.cfg [httpd-promise] <= monitor-promise-base module = check_port_listening name = httpd.py config-hostname = ${httpd:host} config-port = ${httpd:port} {% endif %} [monitor-instance-parameter] monitor-httpd-port = 8026 monitor-title = {{ slapparameter_dict.get('name', 'KVM Standalone') }} cors-domains = {{ slapparameter_dict.get('monitor-cors-domains', 'monitor.app.officejs.com') }} {% if slapparameter_dict.get('monitor-username', '') -%} username = {{ slapparameter_dict['monitor-username'] }} {% endif -%} {% if slapparameter_dict.get('monitor-password', '') -%} password = {{ slapparameter_dict['monitor-password'] }} {% endif -%} interface-url = {{ slapparameter_dict.get('monitor-interface-url', 'https://monitor.app.officejs.com') }} # this helper just gives a blank line to insert in multiline values [helper] blank-line = [frontend-port-execute-base] recipe = plone.recipe.command command = set -e port=$(echo '${request-slave-frontend:connection-secure_access}' | cut -d ':' -f 3 | cut -d '/' -f 1) [ -z $port ] && port=443 echo $port > ${:output} update-command = ${:command} stop-on-error = True [frontend-port-execute] <= frontend-port-execute-base secure_access = ${request-slave-frontend:connection-secure_access} output = ${directory:var}/frontend_port.txt [frontend-port] recipe = collective.recipe.shelloutput filename = ${frontend-port-execute:output} commands = port = [ -f '${:filename}' ] && cat '${:filename}' || echo "NotReady" {% if additional_frontend %} [frontend-additional-port-execute] <= frontend-port-execute-base secure_access = ${request-slave-frontend-additional:connection-secure_access} output = ${directory:var}/frontend_additional_port.txt [frontend-additional-port] <= frontend-port filename = ${frontend-additional-port-execute:output} {% endif %} [publish-connection-information] <= monitor-publish recipe = slapos.cookbook:publish ipv6 = ${slap-network-information:global-ipv6} backend-url = https://[${novnc-instance:ip}]:${novnc-instance:port}/vnc.html?host=[${novnc-instance:ip}]&port=${novnc-instance:port}&encrypt=1&password=${kvm-controller-parameter-dict:vnc-passwd} url = ${request-slave-frontend:connection-secure_access}/vnc.html?host=${request-slave-frontend:connection-domain}&port=${frontend-port:port}&encrypt=1&password=${kvm-controller-parameter-dict:vnc-passwd} {% if additional_frontend %} url-additional = ${request-slave-frontend-additional:connection-secure_access}/vnc.html?host=${request-slave-frontend-additional:connection-domain}&port=${frontend-additional-port:port}&encrypt=1&password=${kvm-controller-parameter-dict:vnc-passwd} {% endif %} {% set disk_number = len(storage_dict) -%} maximum-extra-disk-amount = {{ disk_number }} {% set iface = 'ens3' -%} {% if use_nat == 'true' -%} {% set iface = 'ens4' -%} {% if nat_rule_list -%} # Publish NAT port mapping status {% for port in nat_rule_list.split(' ') -%} {% if ':' in port -%} {% set proto, port = port.split(':') -%} {% else -%} {% set proto, port = 'tcp', port -%} {% endif -%} {% set external_port = 10000 + port|int() -%} nat-rule-port-{{proto}}-{{port}} = ${slap-network-information:global-ipv6} : ${6tunnel-{{proto}}-{{external_port}}:ipv6-port} {% if slapparameter_dict.get('publish-nat-url', False) -%} nat-rule-url-{{proto}}-{{port}} = [${slap-network-information:global-ipv6}]:${6tunnel-{{proto}}-{{external_port}}:ipv6-port} {% endif -%} {% endfor -%} {% endif -%} {% endif -%} {% if use_tap == 'true' -%} tap-ipv4 = {{ slap_configuration.get('tap-ipv4-addr', '') }} tap-ipv6 = {{ slap_configuration.get('tap-ipv6-addr', '') }} {% endif -%} {% set kvm_http = 'http://${slap-network-information:local-ipv4}:' ~ slapparameter_dict.get('httpd-port', 8081) -%} {% if enable_http == 'true' %} {% if use_nat == 'true' -%} {% set kvm_http = 'http://10.0.2.100' -%} {% endif %} {% if slapparameter_dict.get('authorized-key', '') and slapparameter_dict.get('type', '') == 'cluster' -%} key_info = Get the publick key file in your VM with the command: wget {{ kvm_http }}/authorized_keys {% endif %} {% endif %} {% if use_tap == 'true' and slap_configuration.get('tap-ipv4-addr') -%} ipv4-network-info = PERMANENT SOLUTION: in your VM, add the lines below in /etc/network/interfaces and then run: "ifup {{ iface }}" auto {{ iface }} iface {{ iface }} inet static address {{ slap_configuration.get('tap-ipv4-addr') }} netmask {{ slap_configuration.get('tap-ipv4-netmask') }} gateway {{ slap_configuration.get('tap-ipv4-gateway') }} {% if enable_http == 'true' %} ${helper:blank-line} TEMPORARY SOLUTION: run in your VM the command: "wget -O- {{ kvm_http }}/${network-config-ipv4:filename} | /bin/sh -" (the configuration will be gone after the next reboot) {% endif %} {% endif %} ipv6-network-info = {% if use_tap == 'true' and slap_configuration.get('tap-ipv6-addr') %} PERMANENT SOLUTION: in your VM, add the lines below in /etc/network/interfaces and then run: "ifup {{ iface }}" 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') }} {% if enable_http == 'true' %} ${helper:blank-line} 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) {% endif %} {% endif %} {% if use_tap == 'true' and slap_configuration.get('tap-ipv4-addr') -%} [network-config-ipv4] recipe = plone.recipe.command filename = netconfig.sh path = ${directory:public}/${:filename} ipv4-add-address = ip -4 address add {{ slap_configuration.get('tap-ipv4-addr') }}/{{ slap_configuration.get('tap-ipv4-netmask') }} dev \$IFACE {% if nat_restrict == 'true' -%} ipv4-add-default-route = ip route add default via {{ slap_configuration.get('tap-ipv4-gateway') }} dev \$IFACE {% elif global_ipv4_prefix -%} 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') }} {% else -%} ipv4-add-default-route = {% endif -%} ipv4-set-link-up = ip link set dev \$IFACE up command = cat > ${:path} << EOF #!/bin/sh IFACE={{ iface }} #try to be compatible with OS with old names ip a | grep eth0: && [ \$IFACE = ens3 ] && IFACE=eth0 ip a | grep eth1: && [ \$IFACE = ens4 ] && IFACE=eth1 ${:ipv4-add-address} ${:ipv4-add-default-route} ${:ipv4-set-link-up} EOF update-command = ${:command} {% endif -%} {% if use_tap == 'true' and slap_configuration.get('tap-ipv6-addr') -%} [network-config-ipv6] recipe = plone.recipe.command 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 ipv6-add-default-route = 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 command = cat > ${:path} << EOF #!/bin/sh IFACE={{ iface }} ${:ipv6-add-address} ${:ipv6-add-default-route} ${:ipv6-set-link-up} EOF update-command = ${:command} {% endif -%} {% 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') }} {% if slapparameter_dict.get('authorized-key', '') -%} # write public key for vms to public/authorized_keys {{ writefile('get-authorized-key', '${directory:public}/authorized_keys', slapparameter_dict.get('authorized-key', ''), '700') }} {% endif -%} {% if use_tap == 'true' and nat_restrict == 'true' -%} # 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 -%} [publish-host-config] recipe = plone.recipe.command name = {{ slapparameter_dict.get('name', 'localhost') }} {% if use_tap == 'true' and slap_configuration.get('tap-ipv4-addr') -%} local-ipv4 = {{ slap_configuration['tap-ipv4-addr'] }} gateway = {{ slap_configuration.get('tap-ipv4-gateway') }} netmask = {{ slap_configuration.get('tap-ipv4-network') }} network = {{ slap_configuration.get('tap-ipv4-netmask') }} {% else -%} local-ipv4 = 127.0.0.1 gateway = netmask = network = {% endif -%} path-host = ${directory:public}/hostname path-ip = ${directory:public}/ipv4 path-gateway = ${directory:public}/gateway path-network = ${directory:public}/network path-netmask = ${directory:public}/netmask command = rm -f ${:path-host} rm -f ${:path-ip} rm -f ${:path-gateway} rm -f ${:path-network} rm -f ${:path-netmask} echo "${:name}" > ${:path-host} echo "${:local-ipv4}" > ${:path-ip} echo "${:gateway}" > ${:path-gateway} echo "${:network}" > ${:path-network} echo "${:netmask}" > ${:path-netmask} update-command = ${:command} # 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 }} 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 hash-existing-files = ${buildout:directory}/software_release/buildout.cfg [ansible-vm-bin] recipe = slapos.recipe.template:jinja2 template = {{ ansible_promise_tpl }} rendered = ${directory:bin}/ansible_{{ name }} extensions = jinja2.ext.do context = raw logs ${directory:public}/ansible raw name {{ name }} [ansible-vm-promise] <= monitor-promise-base module = check_execute_comand name = ansible_{{ name }}.py config-command = ${ansible-vm-bin:rendered} [download-bootstrap-script] recipe = plone.recipe.command file-location = ${directory:public}/vm-bootstrap command = {{ python_executable }} {{ file_download_script }} {{ bootstrap_url }} {{ bootstrap_url_md5sum }} ${:file-location} update-command = stop-on-error = true [logrotate-vm-bootstrap] < = logrotate-entry-base name = vm-bootstrap log = ${directory:public}/ansible/vm-bootstrap.log [slap-parameter] # Default values if not specified frontend-software-type = RootSoftwareInstance frontend-software-url = http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg frontend-instance-guid = 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 nbd-port = 1024 nbd-host = nbd2-port = 1024 nbd2-host = enable-device-hotplug = False ram-size = 1024 ram-max-size = 51200 ram-hotplug-slot-size = 512 disk-size = 10 disk-type = virtio disk-format = qcow2 disk-device-path = cpu-count = 1 cpu-max-count = 24 disk-cache = writeback disk-aio = native auto-ballooning = True machine-options = cpu-model = host nat-rules = 22 80 443 use-nat = True use-tap = True nat-restrict-mode = False enable-vhost = False virtual-hard-drive-url = virtual-hard-drive-md5sum = virtual-hard-drive-gzipped = False # if virtual-hard-drive-url use https, then specify if https certificate should be checked or not hard-drive-url-check-certificate = True external-disk-number = 0 external-disk-size = 20 external-disk-format = qcow2 # Help to get some configuration files into the vm from http enable-http-server = False httpd-port = 8081 # 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 authorized-key = # send some content which will be accessible to the vm through static url: http://10.0.2.100/data data-to-vm = # Change keyboard layout language (Change to en-us if you face some bad bihaviors) keyboard-layout-language = fr ############################# # # Instanciate kvm (Buildout Section) # ############################# {% if slapparameter_dict.get('document-host', '') %} # Set Additionals parts {% do part_list.append('cluster-url-path') -%} {% endif -%} {% if enable_http == 'true' %} {% do part_list.extend(['httpd', 'httpd-service', 'httpd-promise', 'publish-host-config']) -%} {% if slapparameter_dict.get('data-to-vm', '') %} {% do part_list.append('vm-data-content') -%} {% endif -%} {% if disable_ansible_promise == 'false' %} {% do part_list.extend(['ansible-vm-promise', 'logrotate-vm-bootstrap']) -%} {% endif -%} {% if slapparameter_dict.get('authorized-key', '') and slapparameter_dict.get('type', '') == 'cluster' %} {% do part_list.append('get-authorized-key') -%} {% endif -%} {% if slapparameter_dict.get('bootstrap-script-url', '') -%} {% do part_list.append('download-bootstrap-script') -%} {% endif -%} {% if slapparameter_dict.get('document-port', '') -%} {% do part_list.append('tunnel-cluster-service') -%} {% endif -%} {% endif -%} {% if disk_device_path %} {% do part_list.append('disk-device-permission') -%} [disk-device-permission] recipe = slapos.recipe.template:jinja2 template = inline: {%- raw %} [{"disk": "{{disk_device_path}}"}] {% endraw -%} rendered = ${buildout:directory}/.slapos-disk-permission context = raw disk_device_path {{disk_device_path}} {% endif -%} [buildout] parts = certificate-authority certificate-authority-service publish-connection-information kvm-instance kvm-controller-wrapper kvm-vnc-promise kvm-disk-image-corruption-promise websockify-sighandler websockify-sighandler-service novnc-promise kvm-started-promise cron cron-service cron-entry-logrotate frontend-promise {% if additional_frontend %} frontend-additional-promise {% endif %} # monitor parts monitor-base # Complete parts with sections {{ part_list | join('\n ') }} extends = # Add extends list {{ extends_list | join('\n ') }} # {{ template_httpd_cfg }} eggs-directory = {{ eggs_directory }} develop-eggs-directory = {{ develop_eggs_directory }} offline = true