Commit fa8a4f73 authored by Łukasz Nowak's avatar Łukasz Nowak Committed by Łukasz Nowak

caddy-frontend: Implement non-zero knowledge backward compatible behaviour

parent 28a1283d
......@@ -14,7 +14,7 @@
# not need these here).
[template]
filename = instance.cfg.in
md5sum = ffaf426c68b2f7a35558bf187b5981b7
md5sum = 9906c7722c4fe7534cb5a397c9692553
[template-common]
filename = instance-common.cfg.in
......@@ -22,15 +22,15 @@ md5sum = c801b7f9f11f0965677c22e6bbe9281b
[template-apache-frontend]
filename = instance-apache-frontend.cfg.in
md5sum = b3275d8203b36506ea0f2f9c12f86399
md5sum = 87558ff8adfebac0e53ebc797b5cdffa
[template-apache-replicate]
filename = instance-apache-replicate.cfg.in
md5sum = ab77522560589fc315ddb6c8d28c4015
md5sum = 3344628355c45a7c38bf6c74878f80a5
[template-slave-list]
filename = templates/apache-custom-slave-list.cfg.in
md5sum = ed9743c1a5c1564c7083113ab54b78e3
md5sum = 8bed2dcba7904a765c29cf8349b7d5cc
[template-slave-configuration]
filename = templates/custom-virtualhost.conf.in
......@@ -38,11 +38,11 @@ md5sum = 54ae95597a126ae552c3a913ddf29e5e
[template-replicate-publish-slave-information]
filename = templates/replicate-publish-slave-information.cfg.in
md5sum = 125181ce0065b2acddb0e3ee38f81864
md5sum = 38e9994be01ea1b8a379f8ff7aa05438
[template-caddy-frontend-configuration]
filename = templates/Caddyfile.in
md5sum = 1814950fe926b4a5f730d81d52cc827f
md5sum = d1f22ffd1567f86091e857e53afc0959
[caddy-backend-url-validator]
filename = templates/caddy-backend-url-validator.in
......@@ -58,7 +58,7 @@ md5sum = f20d6c3d2d94fb685f8d26dfca1e822b
[template-default-slave-virtualhost]
filename = templates/default-virtualhost.conf.in
md5sum = ce86264b0c4cc1d447edf40db34e01c4
md5sum = add17b5d1848bee6569c028bc1aea74c
[template-cached-slave-virtualhost]
filename = templates/cached-virtualhost.conf.in
......@@ -86,7 +86,7 @@ md5sum = 117238225b3fc3c5b5be381815f44c67
[template-nginx-configuration]
filename = templates/nginx.cfg.in
md5sum = e5b65b424d01fa539c92f4ba10e847eb
md5sum = d3a5ffd1020f7c7747ba5d360ecf9e72
[template-nginx-eventsource-slave-virtualhost]
filename = templates/nginx-eventsource-slave.conf.in
......@@ -94,7 +94,7 @@ md5sum = 217a6c801b8330b0b825f7b8b4c77184
[template-nginx-notebook-slave-virtualhost]
filename = templates/nginx-notebook-slave.conf.in
md5sum = 3fd1fefaec2d630eee54f75e7a873c27
md5sum = 82834235d2256bec4b4d62e5ba0d302e
[template-apache-lazy-script-call]
filename = templates/apache-lazy-script-call.sh.in
......
......@@ -83,6 +83,9 @@ cron-entries = ${:etc}/cron.d
crontabs = ${:etc}/crontabs
cronstamps = ${:etc}/cronstamps
ca-dir = ${:srv}/ssl
# BBB: SlapOS Master non-zero knowledge BEGIN
bbb-ssl-dir = ${:srv}/bbb-ssl
# BBB: SlapOS Master non-zero knowledge END
varnginx = ${:var}/nginx
......@@ -135,6 +138,7 @@ command =
[jinja2-template-base]
recipe = slapos.recipe.template:jinja2
rendered = ${buildout:directory}/${:filename}
extensions = jinja2.ext.do
extra-context =
slapparameter_dict = {{ dumps(instance_parameter['configuration']) }}
slap_software_type = {{ dumps(instance_parameter['slap-software-type']) }}
......@@ -202,7 +206,6 @@ stop-on-error = True
< = jinja2-template-base
template = {{ parameter_dict['template_slave_list'] }}
filename = custom-personal-instance-slave-list.cfg
extensions = jinja2.ext.do
slave_instance_list = {{ dumps(instance_parameter['slave-instance-list']) }}
extra_slave_instance_list = {{ dumps(instance_parameter.get('configuration.extra_slave_instance_list')) }}
master_key_download_url = {{ dumps(slapparameter_dict['master-key-download-url']) }}
......@@ -280,12 +283,16 @@ extra-context =
key service_directory directory:service
key run_directory directory:etc-run
key not_found_file caddy-configuration:not-found-file
# BBB: SlapOS Master non-zero knowledge BEGIN
key custom_ssl_directory caddy-directory:custom-ssl-directory
key apache_certificate apache-certificate:rendered
key apache_key apache-key:rendered
# BBB: SlapOS Master non-zero knowledge END
[dynamic-virtualhost-template-slave]
<= jinja2-template-base
template = {{ parameter_dict['template_slave_configuration'] }}
rendered = ${directory:template}/slave-virtualhost.conf.in
extensions = jinja2.ext.do
# BBB: apache_custom_https and apache_custom_http
extra-context =
key https_port configuration:port
......@@ -320,6 +327,10 @@ extra-context =
key not_found_file caddy-configuration:not-found-file
key username monitor-instance-parameter:username
key password monitor-htpasswd:passwd
# BBB: SlapOS Master non-zero knowledge BEGIN
key apache_certificate apache-certificate:rendered
key apache_key apache-key:rendered
# BBB: SlapOS Master non-zero knowledge END
[caddy-wrapper]
recipe = slapos.cookbook:wrapper
......@@ -364,6 +375,9 @@ slave-log = ${directory:log}/httpd
nginx-slave-configuration = ${directory:etc}/nginx-slave-conf.d/
autocert = ${directory:srv}/autocert
master-autocert-dir = ${:autocert}/master-autocert
# BBB: SlapOS Master non-zero knowledge BEGIN
custom-ssl-directory = ${:slave-configuration}/ssl
# BBB: SlapOS Master non-zero knowledge END
[caddy-configuration]
frontend-configuration = ${directory:etc}/Caddyfile
......@@ -384,6 +398,24 @@ recipe = slapos.cookbook:wrapper
command-line = ${frontend-caddy-validate:rendered}
wrapper-path = ${directory:bin}/caddy-configtest
# BBB: SlapOS Master non-zero knowledge BEGIN
[apache-key]
< = jinja2-template-base
template = {{ parameter_dict['template_empty'] }}
rendered = ${directory:bbb-ssl-dir}/frontend.key
content = ${configuration:apache-key}
extra-context =
key content :content
[apache-certificate]
< = jinja2-template-base
template = {{ parameter_dict['template_empty'] }}
rendered = ${directory:bbb-ssl-dir}/frontend.crt
content = ${configuration:apache-certificate}
extra-context =
key content :content
# BBB: SlapOS Master non-zero knowledge END
[cron]
recipe = slapos.cookbook:cron
dcrond-binary = {{ parameter_dict['dcron'] }}/sbin/crond
......@@ -561,8 +593,8 @@ config-wrapper-path = ${trafficserver-line:wrapper-path}
template = {{ parameter_dict['template_graceful_script'] }}
rendered = ${directory:etc-run}/frontend-caddy-safe-graceful
mode = 0700
# XXX: Fix path_list for direct ssl ${caddy-directory:vh-ssl}/*.proxy_ca_crt
path_list = ${caddy-configuration:frontend-configuration} ${frontend-configuration:log-access-configuration} ${caddy-directory:slave-configuration}/*.conf ${caddy-directory:slave-with-cache-configuration}/*.conf ${caddy-directory:master-autocert-dir}/*.key ${caddy-directory:master-autocert-dir}/*.crt ${caddy-directory:master-autocert-dir}/*.pem ${caddy-directory:autocert}/*/*.pem
path_list = ${caddy-configuration:frontend-configuration} ${frontend-configuration:log-access-configuration} ${caddy-directory:slave-configuration}/*.conf ${caddy-directory:slave-with-cache-configuration}/*.conf ${caddy-directory:master-autocert-dir}/*.key ${caddy-directory:master-autocert-dir}/*.crt ${caddy-directory:master-autocert-dir}/*.pem ${caddy-directory:autocert}/*/*.pem ${caddy-directory:custom-ssl-directory}/*.key ${caddy-directory:custom-ssl-directory}/*.crt ${caddy-directory:custom-ssl-directory}/*.proxy_ca_crt ${directory:bbb-ssl-dir}/*.key ${directory:bbb-ssl-dir}/*.crt
sha256sum = {{ parameter_dict['sha256sum'] }}
signature_file = ${directory:run}/caddy_graceful_signature
extra-context =
......@@ -576,8 +608,7 @@ extra-context =
template = {{ parameter_dict['template_graceful_script'] }}
rendered = ${directory:etc-run}/frontend-nginx-safe-graceful
mode = 0700
# XXX: Fix path_list for direct ssl ${caddy-directory:vh-ssl}/*.proxy_ca_crt
path_list = ${dynamic-nginx-frontend-template:rendered} ${caddy-directory:nginx-slave-configuration}/*.conf ${caddy-directory:master-autocert-dir}/*.key ${caddy-directory:master-autocert-dir}/*.crt ${caddy-directory:master-autocert-dir}/*.pem ${caddy-directory:autocert}/*/*.pem
path_list = ${dynamic-nginx-frontend-template:rendered} ${caddy-directory:nginx-slave-configuration}/*.conf ${caddy-directory:master-autocert-dir}/*.key ${caddy-directory:master-autocert-dir}/*.crt ${caddy-directory:master-autocert-dir}/*.pem ${caddy-directory:autocert}/*/*.pem ${caddy-directory:custom-ssl-directory}/*.key ${caddy-directory:custom-ssl-directory}/*.crt ${caddy-directory:custom-ssl-directory}/*.proxy_ca_crt ${directory:bbb-ssl-dir}/*.key ${directory:bbb-ssl-dir}/*.crt
sha256sum = {{ parameter_dict['sha256sum'] }}
signature_file = ${directory:run}/nginx_graceful_signature
extra-context =
......@@ -778,6 +809,10 @@ extra-context =
key access_log nginx-configuration:access_log
key not_found_file caddy-configuration:not-found-file
key master_certificate caddy-configuration:master-certificate
# BBB: SlapOS Master non-zero knowledge BEGIN
key apache_certificate apache-certificate:rendered
key apache_key apache-key:rendered
# BBB: SlapOS Master non-zero knowledge END
[nginx-configuration]
access_log = ${directory:log}/nginx-access.log
......
......@@ -72,10 +72,12 @@ context =
{% set authorized_slave_string_list = slapparameter_dict.pop('-frontend-authorized-slave-string', '').split() %}
{% set authorized_slave_list = [] %}
{% set rejected_slave_dict = {} %}
{% set warning_slave_dict = {} %}
{% set used_host_list = [] %}
{% set unauthorized_message = 'slave not authorized' %}
{% for slave in slave_instance_list %}
{% set slave_error_list = [] %}
{% set slave_warning_list = [] %}
{% set slave_server_alias_unclashed = [] %}
{# BBB: apache_custom_https AND apache_custom_http #}
{% set custom_domain = slave.get('custom_domain') %}
......@@ -127,6 +129,25 @@ context =
{% do slave_error_list.append('slave https-url %r invalid' % (slave['https-url'],)) %}
{% endif %}
{% endif %}
{# BBB: SlapOS Master non-zero knowledge BEGIN #}
{% for key in ['ssl_key', 'ssl_crt', 'ssl_ca_crt'] %}
{% if key in slave %}
{% do slave_warning_list.append('%s is obsolete, please use key-upload-url' % (key,)) %}
{% endif %}
{% endfor %}
{% if slave.get('ssl_ca_crt') and not (slave.get('ssl_crt') and slave.get('ssl_key')) %}
{% do slave_error_list.append('ssl_ca_crt is present, so ssl_crt and ssl_key are required') %}
{% endif %}
{% if slave.get('ssl_key') and slave.get('ssl_crt') %}
{% set key_popen = popen([parameter_dict['openssl'], 'rsa', '-noout', '-modulus']) %}
{% set crt_popen = popen([parameter_dict['openssl'], 'x509', '-noout', '-modulus']) %}
{% set key_modulus = key_popen.communicate(slave['ssl_key'])[0] | trim %}
{% set crt_modulus = crt_popen.communicate(slave['ssl_crt'])[0] | trim %}
{% if not key_modulus or key_modulus != crt_modulus %}
{% do slave_error_list.append('slave ssl_key and ssl_crt does not match') %}
{% endif %}
{% endif %}
{# BBB: SlapOS Master non-zero knowledge END #}
{% if slave.get('custom_domain') %}
{% set slave_custom_domain = '' ~ slave['custom_domain'] %}
{% if slave_custom_domain.startswith('*.') %}
......@@ -143,6 +164,9 @@ context =
{% else %}
{% do rejected_slave_dict.__setitem__(slave.get('slave_reference'), slave_error_list) %}
{% endif %}
{% if len(slave_warning_list) > 0 %}
{% do warning_slave_dict.__setitem__(slave.get('slave_reference'), slave_warning_list) %}
{% endif %}
{% endfor %}
[monitor-instance-parameter]
......@@ -189,6 +213,12 @@ sla-{{ parameter }} = {{ value }}
{% endif %}
{% endfor %}
{% set warning_list = [] %}
{% for key in ['apache-certificate', 'apache-key'] %}
{% if key in slapparameter_dict %}
{% do warning_list.append('%s is obsolete, please use master-key-upload-url' % (key, )) %}
{% endif %}
{% endfor %}
[publish-information]
<= monitor-publish
......@@ -201,6 +231,12 @@ rejected-slave-dict = {{ dumps(json_module.dumps(rejected_slave_dict)) }}
master-key-upload-url = ${request-kedifa:connection-master-key-upload-url}
master-key-generate-auth-url = ${request-kedifa:connection-master-key-generate-auth-url}
kedifa-caucase-url = ${request-kedifa:connection-caucase-url}
{% if len(warning_list) > 0 %}
warning-list = {{ dumps(json_module.dumps(warning_list)) }}
{% endif %}
{% if len(warning_slave_dict) > 0 %}
warning-slave-dict = {{ dumps(json_module.dumps(warning_slave_dict)) }}
{% endif %}
{% if not aikc_enabled %}
kedifa-csr_id-url = ${request-kedifa:connection-csr_id-url}
kedifa-csr_id-certificate = ${request-kedifa:connection-csr_id-certificate}
......@@ -258,6 +294,11 @@ sla-{{ key[sla_kedifa_key_length:] }} = {{ slapparameter_dict.pop(key) }}
{{ slave_id }} = {{ dumps(json_module.dumps(rejected_list)) }}
{% endfor %}
[warning-slave-information]
{% for slave_id, warning_list in warning_slave_dict.iteritems() %}
{{ slave_id }} = {{ dumps(json_module.dumps(warning_list)) }}
{% endfor %}
[slave-information]
{% for frontend_section in frontend_section_list %}
{{ frontend_section }} = {{ "${%s:connection-slave-instance-information-list}" % frontend_section }}
......@@ -281,6 +322,7 @@ extra-context =
section slave_information slave-information
section rejected_slave_information rejected-slave-information
section active_slave_instance_dict active-slave-instance
section warning_slave_information warning-slave-information
key slave_kedifa_information request-kedifa:connection-slave-kedifa-information
[monitor-conf-parameters]
......
......@@ -106,6 +106,8 @@ configuration.apache_custom_https = ""
configuration.apache_custom_http = ""
configuration.caddy_custom_https = ""
configuration.caddy_custom_http = ""
configuration.apache-key =
configuration.apache-certificate =
configuration.open-port = 80 443
configuration.disk-cache-size = 8G
configuration.ram-cache-size = 1G
......
......@@ -4,10 +4,20 @@ import {{frontend_configuration.get('log-access-configuration')}}
import {{ slave_configuration_directory }}/*.conf
import {{ slave_with_cache_configuration_directory }}/*.conf
{%- set ssl = {} -%}
{%- if os_module.path.exists(master_certificate) -%}
{%- do ssl.__setitem__('certificate', master_certificate) -%}
{%- do ssl.__setitem__('key', master_certificate) -%}
{#- BBB: SlapOS Master non-zero knowledge BEGIN -#}
{%- elif os_module.path.getsize(apache_certificate) > 0 and os_module.path.getsize(apache_key) > 0 -%}
{%- do ssl.__setitem__('certificate', apache_certificate) -%}
{%- do ssl.__setitem__('key', apache_key) -%}
{%- endif -%}
{#- BBB: SlapOS Master non-zero knowledge END #}
# Catch-all and 404 for not configured instances
{% if os_module.path.exists(master_certificate) %}
{% if 'key' in ssl %}
:{{ https_port }} {
tls {{ master_certificate }} {{ master_certificate }}
tls {{ ssl['certificate'] }} {{ ssl['key'] }}
bind {{ local_ipv4 }}
# Compress the output
gzip
......
......@@ -208,6 +208,61 @@ command =
fi
update-command = ${:command}
# BBB: SlapOS Master non-zero knowledge BEGIN
{# Set ssl certificates for each slave #}
{% for cert_name in ('ssl_csr', 'ssl_proxy_ca_crt')%}
{% if cert_name in slave_instance %}
{% set cert_title = '%s-%s' % (slave_reference, cert_name.replace('ssl_', '')) %}
{% set cert_file = '/'.join([custom_ssl_directory, cert_title.replace('-','.')]) %}
{% do part_list.append(cert_title) %}
{% do slave_parameter_dict.__setitem__(cert_name, cert_file) %}
{% do slave_instance.__setitem__('path_to_' + cert_name, cert_file) %}
{# Store certificates on fs #}
[{{ cert_title }}]
< = jinja2-template-base
template = {{ empty_template }}
rendered = {{ cert_file }}
extra-context =
key content {{ cert_title + '-config:value' }}
# Store certificate in config
[{{ cert_title + '-config' }}]
value = {{ dumps(slave_instance.get(cert_name)) }}
{% endif %}
{% endfor %}
{#- Set Up Certs #}
{% do slave_instance.__setitem__('apache_certificate', apache_certificate) %}
{% do slave_instance.__setitem__('apache_key', apache_key) %}
{% if 'ssl_key' in slave_instance and 'ssl_crt' in slave_instance %}
{% set cert_title = '%s-crt' % (slave_reference) %}
{% set key_title = '%s-key' % (slave_reference) %}
{% set cert_file = '/'.join([custom_ssl_directory, cert_title.replace('-','.')]) %}
{% set key_file = '/'.join([custom_ssl_directory, key_title.replace('-','.')]) %}
{% do part_list.append(cert_title) %}
{% do part_list.append(key_title) %}
{% do slave_parameter_dict.__setitem__("ssl_crt", cert_file) %}
{% do slave_parameter_dict.__setitem__("ssl_key", key_file) %}
{% do slave_instance.__setitem__('path_to_ssl_crt', cert_file) %}
{% do slave_instance.__setitem__('path_to_ssl_key', key_file) %}
[{{key_title}}]
< = jinja2-template-base
template = {{ empty_template }}
rendered = {{ key_file }}
key-content = {{ dumps(slave_instance.get('ssl_key')) }}
extra-context =
key content :key-content
[{{cert_title}}]
< = jinja2-template-base
template = {{ empty_template }}
rendered = {{ cert_file }}
cert-content = {{ dumps(slave_instance.get('ssl_crt') + '\n' + slave_instance.get('ssl_ca_crt', '')) }}
extra-context =
key content :cert-content
{% endif %}
# BBB: SlapOS Master non-zero knowledge END
{# ########################################## #}
{# Set Slave Configuration #}
[{{ slave_configuration_section_name }}]
......
......@@ -26,12 +26,25 @@
{%- set default_path = slave_parameter.get('default-path', '').strip('/') | urlencode %}
# SSL enabled hosts
{% set ssl = {} %}
{% if os_module.path.exists(slave_parameter['certificate']) %}
{% do ssl.__setitem__('certificate', slave_parameter['certificate']) %}
{% do ssl.__setitem__('key', slave_parameter['certificate']) %}
{#- BBB: SlapOS Master non-zero knowledge BEGIN -#}
{% elif 'path_to_ssl_crt' in slave_parameter and 'path_to_ssl_key' in slave_parameter %}
{% do ssl.__setitem__('certificate', slave_parameter['path_to_ssl_crt']) %}
{% do ssl.__setitem__('key', slave_parameter['path_to_ssl_key']) %}
{% elif os_module.path.getsize(slave_parameter['apache_certificate']) > 0 and os_module.path.getsize(slave_parameter['apache_key']) > 0 %}
{% do ssl.__setitem__('certificate', slave_parameter['apache_certificate']) %}
{% do ssl.__setitem__('key', slave_parameter['apache_key']) %}
{% endif %}
{#- BBB: SlapOS Master non-zero knowledge END -#}
{% if 'key' in ssl %}
{{ https_host_list|join(', ') }} {
bind {{ slave_parameter['local_ipv4'] }}
# Compress the output
gzip
tls {{ slave_parameter['certificate'] }} {{ slave_parameter['certificate'] }} {
tls {{ ssl['certificate'] }} {{ ssl['key'] }} {
{%- if enable_h2 %}
# Allow HTTP2
alpn h2 http/1.1
......
......@@ -5,7 +5,20 @@
{%- set https_upstream = https_url.split("/")[2] %}
# SSL-enabled
{% set ssl = {} %}
{% if os_module.path.exists(slave_parameter['certificate']) %}
{% do ssl.__setitem__('certificate', slave_parameter['certificate']) %}
{% do ssl.__setitem__('key', slave_parameter['certificate']) %}
{#- BBB: SlapOS Master non-zero knowledge BEGIN -#}
{% elif 'path_to_ssl_crt' in slave_parameter and 'path_to_ssl_key' in slave_parameter %}
{% do ssl.__setitem__('certificate', slave_parameter['path_to_ssl_crt']) %}
{% do ssl.__setitem__('key', slave_parameter['path_to_ssl_key']) %}
{% elif os_module.path.getsize(slave_parameter['apache_certificate']) > 0 and os_module.path.getsize(slave_parameter['apache_key']) > 0 %}
{% do ssl.__setitem__('certificate', slave_parameter['apache_certificate']) %}
{% do ssl.__setitem__('key', slave_parameter['apache_key']) %}
{% endif %}
{#- BBB: SlapOS Master non-zero knowledge END -#}
{% if 'key' in ssl %}
https://{{ slave_parameter.get('custom_domain') }}:{{ slave_parameter['nginx_https_port'] }} {
bind {{ slave_parameter['local_ipv4'] }}
# Compress the output
......@@ -13,7 +26,7 @@ https://{{ slave_parameter.get('custom_domain') }}:{{ slave_parameter['nginx_htt
log / {{ slave_parameter.get('access_log') }} "{remote} {>REMOTE_USER} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\" {latency_ms}"
errors {{ slave_parameter.get('error_log') }}
tls {{ slave_parameter['certificate'] }} {{ slave_parameter['certificate'] }} {
tls {{ ssl['certificate'] }} {{ ssl['key'] }} {
alpn http/1.1
}
......
......@@ -58,9 +58,20 @@
import {{ slave_configuration_directory }}/*.conf
# Catch-all and 404 for not configured instances
{% if os_module.path.exists(master_certificate) %}
{%- set ssl = {} -%}
{%- if os_module.path.exists(master_certificate) -%}
{%- do ssl.__setitem__('certificate', master_certificate) -%}
{%- do ssl.__setitem__('key', master_certificate) -%}
{#- BBB: SlapOS Master non-zero knowledge BEGIN -#}
{%- elif os_module.path.getsize(apache_certificate) > 0 and os_module.path.getsize(apache_key) > 0 -%}
{%- do ssl.__setitem__('certificate', apache_certificate) -%}
{%- do ssl.__setitem__('key', apache_key) -%}
{%- endif -%}
{#- BBB: SlapOS Master non-zero knowledge END -#}
# Catch-all and 404 for not configured instances
{% if 'key' in ssl %}
:{{ port }} {
tls {{ master_certificate }} {{ master_certificate }}
tls {{ ssl['certificate'] }} {{ ssl['key'] }}
bind {{ local_ip }}
# Serve an error 204 (No Content) for favicon.ico
status 204 /favicon.ico
......
......@@ -34,6 +34,13 @@
{% do slave_information_dict[slave_reference].__setitem__('request-error-list', rejected_info_list) %}
{% endfor %}
{% for slave_reference, warning_info_list in warning_slave_information.iteritems() %}
{% if slave_reference not in slave_information_dict %}
{% do slave_information_dict.__setitem__(slave_reference, {}) %}
{% endif %}
{% do slave_information_dict[slave_reference].__setitem__('warning-list', warning_info_list) %}
{% endfor %}
{% for slave_reference, kedifa_dict in json_module.loads(slave_kedifa_information).iteritems() %}
{% if slave_reference not in rejected_slave_information %}
{% if slave_reference not in slave_information_dict %}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment