Commit 0a0eb065 authored by Kirill Smelkov's avatar Kirill Smelkov

Merge branch 'x/lte-multiru' into xy/lte-multiru

- more B quotes
- Inter-RAT HO fixup
- robustify behaviour when no RU is configured
parents 6d5df7c8 38f41981
...@@ -45,10 +45,8 @@ class Recipe(GenericBaseRecipe): ...@@ -45,10 +45,8 @@ class Recipe(GenericBaseRecipe):
elif self.options.get('expected-type') == "ipv4": elif self.options.get('expected-type') == "ipv4":
template = self.getTemplateFilename('check_ipv4.py.in') template = self.getTemplateFilename('check_ipv4.py.in')
else: else:
config["expected-value"] = self.options.get('expected-value') config["expected-value"] = str(self.options.get('expected-value', ''))
config["expected-not-value"] = str(self.options.get('expected-not-value', ''))
config["expected-not-value"] = self.options.get('expected-not-value')
template = self.getTemplateFilename('check_parameter.py.in') template = self.getTemplateFilename('check_parameter.py.in')
promise = self.createExecutable( promise = self.createExecutable(
......
...@@ -5,14 +5,14 @@ from __future__ import print_function ...@@ -5,14 +5,14 @@ from __future__ import print_function
import socket import socket
import sys import sys
value = "%(value)s" value = %(value)r
expected = "%(expected-value)s" expected = %(expected-value)r
not_expected = "%(expected-not-value)s" not_expected = %(expected-not-value)r
if expected != "" and value != expected: if expected != "" and value != expected:
print("FAIL: %%s != %%s" %% (value, expected)) print("FAIL: %%s != %%s" %% (value, expected))
sys.exit(127) sys.exit(127)
if not_expected != "" and value == not_expected: if not_expected != "" and value == not_expected:
print("FAIL: %%s == %%s" %% (value, not_expected)) print("FAIL: %%s == %%s" %% (value, not_expected))
sys.exit(127) sys.exit(127)
import os
import subprocess
import tempfile
import unittest
import zc.buildout.testing
from slapos.recipe import check_parameter
class TestCheckParameter(unittest.TestCase):
def setUp(self):
self.buildout = zc.buildout.testing.Buildout()
def _makeRecipe(self, options):
path = tempfile.NamedTemporaryFile(delete=False).name
self.addCleanup(os.unlink, path)
options.setdefault("path", path)
self.buildout["check-parameter"] = options
recipe = check_parameter.Recipe(
self.buildout, "check-parameter", self.buildout["check-parameter"]
)
return recipe
def test_expected_value_ok(self):
script = self._makeRecipe({"expected-value": "foo", "value": "foo"}).install()
subprocess.check_call(script)
def test_expected_value_not_ok(self):
script = self._makeRecipe({"expected-value": "foo", "value": "bar"}).install()
with self.assertRaises(subprocess.CalledProcessError) as e:
subprocess.check_output(script, universal_newlines=True)
self.assertEqual(e.exception.output, "FAIL: bar != foo\n")
def test_expected_value_multi_lines_ok(self):
script = self._makeRecipe(
{"expected-value": "foo\nbar", "value": "foo\nbar"}
).install()
subprocess.check_output(script)
def test_expected_value_multi_lines_not_ok(self):
script = self._makeRecipe({"expected-value": "foo\nbar", "value": "foo"}).install()
with self.assertRaises(subprocess.CalledProcessError) as e:
subprocess.check_output(script, universal_newlines=True)
self.assertEqual(e.exception.output, "FAIL: foo != foo\nbar\n")
def test_expected_not_value_ok(self):
script = self._makeRecipe({"expected-not-value": "foo", "value": "bar"}).install()
subprocess.check_call(script)
def test_expected_not_value_not_ok(self):
script = self._makeRecipe({"expected-not-value": "foo", "value": "foo"}).install()
with self.assertRaises(subprocess.CalledProcessError) as e:
subprocess.check_output(script, universal_newlines=True)
self.assertEqual(e.exception.output, "FAIL: foo == foo\n")
...@@ -1104,7 +1104,7 @@ class TestNEO(ZopeSkinsMixin, CrontabMixin, ERP5InstanceTestCase): ...@@ -1104,7 +1104,7 @@ class TestNEO(ZopeSkinsMixin, CrontabMixin, ERP5InstanceTestCase):
class TestWithMaxRlimitNofileParameter(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin): class TestWithMaxRlimitNofileParameter(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test setting the with-max-rlimit-nofile parameter sets the open fd soft limit to the hard limit. """Test setting the with-max-rlimit-nofile parameter sets the open fd soft limit to the hard limit.
""" """
__partition_reference__ = 'with-max-rlimit-nofile' __partition_reference__ = 'nf'
@classmethod @classmethod
def getInstanceParameterDict(cls): def getInstanceParameterDict(cls):
...@@ -1123,7 +1123,7 @@ class TestWithMaxRlimitNofileParameter(ERP5InstanceTestCase, TestPublishedURLIsR ...@@ -1123,7 +1123,7 @@ class TestWithMaxRlimitNofileParameter(ERP5InstanceTestCase, TestPublishedURLIsR
class TestUnsetWithMaxRlimitNofileParameter(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin): class TestUnsetWithMaxRlimitNofileParameter(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test not setting the with-max-rlimit-nofile parameter doesn't change the soft limit of erp5 """Test not setting the with-max-rlimit-nofile parameter doesn't change the soft limit of erp5
""" """
__partition_reference__ = 'unset-with-max-rlimit-nofile' __partition_reference__ = 'nnf'
def test_unset_with_max_rlimit_nofile(self) -> None: def test_unset_with_max_rlimit_nofile(self) -> None:
with self.slap.instance_supervisor_rpc as supervisor: with self.slap.instance_supervisor_rpc as supervisor:
......
...@@ -24,11 +24,11 @@ md5sum = f5c76c3443b75569eb18503dce38e783 ...@@ -24,11 +24,11 @@ md5sum = f5c76c3443b75569eb18503dce38e783
[slaplte.jinja2] [slaplte.jinja2]
_update_hash_filename_ = slaplte.jinja2 _update_hash_filename_ = slaplte.jinja2
md5sum = fa841e105d78aab36b9ea205a69608fb md5sum = 9c1cf42bbf5286f8ddd4e14f19447d30
[ru_libinstance.jinja2.cfg] [ru_libinstance.jinja2.cfg]
_update_hash_filename_ = ru/libinstance.jinja2.cfg _update_hash_filename_ = ru/libinstance.jinja2.cfg
md5sum = 4c1e6fbd774042cdd12687fd30635c6b md5sum = af0d3626f504af02f22780696820e401
[ru_sdr_libinstance.jinja2.cfg] [ru_sdr_libinstance.jinja2.cfg]
_update_hash_filename_ = ru/sdr/libinstance.jinja2.cfg _update_hash_filename_ = ru/sdr/libinstance.jinja2.cfg
...@@ -112,20 +112,20 @@ md5sum = dcaac06553a3222b14c0013a13f4a149 ...@@ -112,20 +112,20 @@ md5sum = dcaac06553a3222b14c0013a13f4a149
[enb.jinja2.cfg] [enb.jinja2.cfg]
filename = config/enb.jinja2.cfg filename = config/enb.jinja2.cfg
md5sum = 7edbafa743dc17749ff910aca775abbf md5sum = 43ae4e7f94f2c84cef07a273f6b2e668
[drb_lte.jinja2.cfg] [drb_lte.jinja2.cfg]
filename = config/drb_lte.jinja2.cfg filename = config/drb_lte.jinja2.cfg
md5sum = a11c10066c32900931a51abb4d6b0c45 md5sum = 01eb971e2ff580da52291138495a81ca
[drb_nr.jinja2.cfg] [drb_nr.jinja2.cfg]
filename = config/drb_nr.jinja2.cfg filename = config/drb_nr.jinja2.cfg
md5sum = 328c4760ef188c1cccc2ef3c7b68b7f3 md5sum = 282b11d7b72b01b8325df4632d82b84d
[sib23.jinja2.asn] [sib23.jinja2.asn]
filename = config/sib23.jinja2.asn filename = config/sib23.jinja2.asn
md5sum = cbb893a0dd9de6b8f54bcfc21928bad2 md5sum = 959523597e29b048e45ebf58f7ea4c5b
[mme.jinja2.cfg] [mme.jinja2.cfg]
filename = config/mme.jinja2.cfg filename = config/mme.jinja2.cfg
...@@ -137,7 +137,7 @@ md5sum = f167b4be5e327b276b42267e0678f577 ...@@ -137,7 +137,7 @@ md5sum = f167b4be5e327b276b42267e0678f577
[ru_dnsmasq.jinja2.cfg] [ru_dnsmasq.jinja2.cfg]
_update_hash_filename_ = ru/dnsmasq.jinja2.cfg _update_hash_filename_ = ru/dnsmasq.jinja2.cfg
md5sum = ade86715b6121b654552b11d7c756c10 md5sum = 2607e31a5400b8fb03d0f0ced8434a95
[ims.jinja2.cfg] [ims.jinja2.cfg]
filename = config/ims.jinja2.cfg filename = config/ims.jinja2.cfg
......
// DRB configuration for LTE cell {{ cell_ref }} @ {{ ru_ref }}. {%- set B = xbuildout.encode -%}
// DRB configuration for LTE cell {{ B(cell_ref) }} @ {{ B(ru_ref) }}.
// DRB configuration vary in beteen FDD and TDD modes. // DRB configuration vary in beteen FDD and TDD modes.
{% set T_REORDERING = {'fdd': 35, 'tdd': 65} [cell.rf_mode] %} {% set T_REORDERING = {'fdd': 35, 'tdd': 65} [cell.rf_mode] %}
......
// DRB configuration for NR cell {{ cell_ref }} @ {{ ru_ref }}. {%- set B = xbuildout.encode -%}
// DRB configuration for NR cell {{ B(cell_ref) }} @ {{ B(ru_ref) }}.
[ [
{ {
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
n_id_cell: {{ cell2.pci }}, n_id_cell: {{ cell2.pci }},
dl_earfcn: {{ cell2.dl_earfcn }}, dl_earfcn: {{ cell2.dl_earfcn }},
tac: {{ cell2.tac }}, tac: {{ cell2.tac }},
allowed_meas_bandwidth: {{ jlte_n_rb_dl(cell2.bandwidth) }},
antenna_port_1: {{ (ru2.n_antenna_dl > 1) | tojson }},
{%- elif cell2.cell_type == 'nr' %} {%- elif cell2.cell_type == 'nr' %}
rat: "nr", rat: "nr",
cell_id: {{ cell2.cell_id }}, // -> {{ B(cell2_ref) }} cell_id: {{ cell2.cell_id }}, // -> {{ B(cell2_ref) }}
...@@ -62,6 +64,10 @@ ...@@ -62,6 +64,10 @@
n_id_cell: {{ ncell.pci }}, n_id_cell: {{ ncell.pci }},
dl_earfcn: {{ ncell.dl_earfcn }}, dl_earfcn: {{ ncell.dl_earfcn }},
tac: {{ ncell.tac }}, tac: {{ ncell.tac }},
{#- TODO: consider extending peer/cell/lte with
.allowed_meas_bandwidth and .antenna_port_1 #}
allowed_meas_bandwidth: {{ jlte_n_rb_dl(1.4) }}, // XXX minimum possible bw
antenna_port_1: false, // XXX conservative stub
{%- elif ncell.cell_type == 'nr' %} {%- elif ncell.cell_type == 'nr' %}
rat: "nr", rat: "nr",
nr_cell_id: {{ ncell.nr_cell_id }}, // -> {{ B(peercell_ref) }} nr_cell_id: {{ ncell.nr_cell_id }}, // -> {{ B(peercell_ref) }}
......
// DRB configuration for LTE cell CELL_a @ RU1. // DRB configuration for LTE cell CELL__a @ RU1.
// DRB configuration vary in beteen FDD and TDD modes. // DRB configuration vary in beteen FDD and TDD modes.
......
/* SIB2/SIB3 for LTE cell CELL_a @ RU1. */ /* SIB2/SIB3 for LTE cell CELL__a @ RU1. */
{ {
message c1: systemInformation: { message c1: systemInformation: {
criticalExtensions systemInformation-r8: { criticalExtensions systemInformation-r8: {
......
// DRB configuration for NR cell CELL_b @ RU2. // DRB configuration for NR cell CELL__b @ RU2.
[ [
{ {
......
/* SIB2/SIB3 for NR cell CELL_b @ RU2. */ /* SIB2/SIB3 for NR cell CELL__b @ RU2. */
{ {
message c1: systemInformation: { message c1: systemInformation: {
criticalExtensions systemInformation-r8: { criticalExtensions systemInformation-r8: {
......
...@@ -78,6 +78,8 @@ ...@@ -78,6 +78,8 @@
n_id_cell: 35, n_id_cell: 35,
dl_earfcn: 700, dl_earfcn: 700,
tac: 123, tac: 123,
allowed_meas_bandwidth: 6, // XXX minimum possible bw
antenna_port_1: false, // XXX conservative stub
}, },
{ {
rat: "nr", rat: "nr",
...@@ -271,6 +273,8 @@ ...@@ -271,6 +273,8 @@
n_id_cell: 1, n_id_cell: 1,
dl_earfcn: 38050, dl_earfcn: 38050,
tac: 0x1234, tac: 0x1234,
allowed_meas_bandwidth: 25,
antenna_port_1: true,
}, },
// Inter-ENB HO // Inter-ENB HO
...@@ -280,6 +284,8 @@ ...@@ -280,6 +284,8 @@
n_id_cell: 35, n_id_cell: 35,
dl_earfcn: 700, dl_earfcn: 700,
tac: 123, tac: 123,
allowed_meas_bandwidth: 6, // XXX minimum possible bw
antenna_port_1: false, // XXX conservative stub
}, },
{ {
rat: "nr", rat: "nr",
......
/* SIB2/SIB3 for {{ cell.cell_type | upper }} cell {{ cell_ref }} @ {{ ru_ref }}. */ {%- set B = xbuildout.encode -%}
/* SIB2/SIB3 for {{ cell.cell_type | upper }} cell {{ B(cell_ref) }} @ {{ B(ru_ref) }}. */
{ {
message c1: systemInformation: { message c1: systemInformation: {
criticalExtensions systemInformation-r8: { criticalExtensions systemInformation-r8: {
......
{%- set B = xbuildout.encode -%}
dhcp-leasefile={{ directory['etc'] }}/dnsmasq.leases dhcp-leasefile={{ directory['etc'] }}/dnsmasq.leases
port=5354 port=5354
...@@ -7,7 +9,7 @@ port=5354 ...@@ -7,7 +9,7 @@ port=5354
{%- set vtap = json_module.loads(vtap_jdict[ru_tap]) %} {%- set vtap = json_module.loads(vtap_jdict[ru_tap]) %}
{%- set plen = netaddr.IPNetwork(vtap.network).prefixlen %} {%- set plen = netaddr.IPNetwork(vtap.network).prefixlen %}
# {{ ru_ref }} @ {{ ru_tap }} # {{ B(ru_ref) }} @ {{ ru_tap }}
dhcp-range=tag:{{ ru_tap }},{{ vtap.gateway }},{{ vtap.gateway }},static,{{ plen }},5m dhcp-range=tag:{{ ru_tap }},{{ vtap.gateway }},{{ vtap.gateway }},static,{{ plen }},5m
dhcp-host={{ ru.mac_addr }},tag:{{ ru_tap }},[{{ vtap.gateway }}] dhcp-host={{ ru.mac_addr }},tag:{{ ru_tap }},[{{ vtap.gateway }}]
# option 17 used for RU callhome # option 17 used for RU callhome
......
...@@ -149,6 +149,7 @@ filename = dnsmasq.cfg ...@@ -149,6 +149,7 @@ filename = dnsmasq.cfg
extensions = jinja2.ext.do extensions = jinja2.ext.do
output = ${directory:etc}/${:filename} output = ${directory:etc}/${:filename}
context = context =
import xbuildout xbuildout
import json_module json import json_module json
import netaddr netaddr import netaddr netaddr
section directory directory section directory directory
......
...@@ -439,7 +439,7 @@ ...@@ -439,7 +439,7 @@
{%- do tx_gainv.extend([ru.tx_gain]*ru.n_antenna_dl) %} {%- do tx_gainv.extend([ru.tx_gain]*ru.n_antenna_dl) %}
{%- do rx_gainv.extend([ru.rx_gain]*ru.n_antenna_ul) %} {%- do rx_gainv.extend([ru.rx_gain]*ru.n_antenna_ul) %}
{%- endfor %} {%- endfor %}
args: "{{dev_argv | join(',')}}", args: "{{(dev_argv | join(',')) or '---'}}",
{#- emit sdr-related options if an sdr ru is present #} {#- emit sdr-related options if an sdr ru is present #}
{%- if len(ru_sdr_dict) > 0 %} {%- if len(ru_sdr_dict) > 0 %}
......
...@@ -136,7 +136,6 @@ enb_param_dict.update(param_dict) ...@@ -136,7 +136,6 @@ enb_param_dict.update(param_dict)
gnb_param_dict1.update(param_dict) gnb_param_dict1.update(param_dict)
gnb_param_dict2.update(param_dict) gnb_param_dict2.update(param_dict)
def test_enb_conf(self): def test_enb_conf(self):
conf_file = glob.glob(os.path.join( conf_file = glob.glob(os.path.join(
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
# not need these here). # not need these here).
[template-erp5] [template-erp5]
filename = instance-erp5.cfg.in filename = instance-erp5.cfg.in
md5sum = c605292e57a12e42d9c2676e38c072c6 md5sum = 1fbfca2d64a9824054f7a3281e71efdc
[template-balancer] [template-balancer]
filename = instance-balancer.cfg.in filename = instance-balancer.cfg.in
......
...@@ -309,7 +309,7 @@ config-webdav = {{ dumps(current_zope_family_override_dict.get('webdav', zope_pa ...@@ -309,7 +309,7 @@ config-webdav = {{ dumps(current_zope_family_override_dict.get('webdav', zope_pa
config-publisher-timeout = {{ dumps(current_zope_family_override_dict.get('publisher-timeout', global_publisher_timeout)) }} config-publisher-timeout = {{ dumps(current_zope_family_override_dict.get('publisher-timeout', global_publisher_timeout)) }}
config-activity-timeout = {{ dumps(current_zope_family_override_dict.get('activity-timeout', global_activity_timeout)) }} config-activity-timeout = {{ dumps(current_zope_family_override_dict.get('activity-timeout', global_activity_timeout)) }}
{% if test_runner_enabled -%} {% if test_runner_enabled -%}
config-test-runner-apache-url-list = ${publish-early:{{ zope_family }}-test-runner-url-list} config-test-runner-balancer-url-list = ${publish-early:{{ zope_family }}-test-runner-url-list}
[{{ promise_software_url_section_name }}] [{{ promise_software_url_section_name }}]
# Promise to wait for zope partition to use the expected software URL, # Promise to wait for zope partition to use the expected software URL,
......
...@@ -74,7 +74,7 @@ md5sum = 55232eae0bcdb68a7cb2598d2ba9d60c ...@@ -74,7 +74,7 @@ md5sum = 55232eae0bcdb68a7cb2598d2ba9d60c
[template-erp5] [template-erp5]
filename = instance-erp5.cfg.in filename = instance-erp5.cfg.in
md5sum = 2bb2addc8deddff00053a065f5e2793e md5sum = 359bab24aec7772adb5d822c1389b1bd
[template-zeo] [template-zeo]
filename = instance-zeo.cfg.in filename = instance-zeo.cfg.in
...@@ -86,7 +86,7 @@ md5sum = 0ac4b74436f554cd677f19275d18d880 ...@@ -86,7 +86,7 @@ md5sum = 0ac4b74436f554cd677f19275d18d880
[template-zope] [template-zope]
filename = instance-zope.cfg.in filename = instance-zope.cfg.in
md5sum = 8a2c78000e1e791dc48305a2e7330b16 md5sum = 2439b90d6f707f47050fc9074fa4d810
[template-balancer] [template-balancer]
filename = instance-balancer.cfg.in filename = instance-balancer.cfg.in
......
...@@ -321,12 +321,12 @@ config-webdav = {{ dumps(current_zope_family_override_dict.get('webdav', zope_pa ...@@ -321,12 +321,12 @@ config-webdav = {{ dumps(current_zope_family_override_dict.get('webdav', zope_pa
config-publisher-timeout = {{ dumps(current_zope_family_override_dict.get('publisher-timeout', global_publisher_timeout)) }} config-publisher-timeout = {{ dumps(current_zope_family_override_dict.get('publisher-timeout', global_publisher_timeout)) }}
config-activity-timeout = {{ dumps(current_zope_family_override_dict.get('activity-timeout', global_activity_timeout)) }} config-activity-timeout = {{ dumps(current_zope_family_override_dict.get('activity-timeout', global_activity_timeout)) }}
{% if test_runner_enabled -%} {% if test_runner_enabled -%}
config-test-runner-apache-url-list = ${publish-early:{{ zope_family }}-test-runner-url-list} config-test-runner-balancer-url-list = ${publish-early:{{ zope_family }}-test-runner-url-list}
[{{ check_test_runner_url_section_name }}] [{{ check_test_runner_url_section_name }}]
# Promise to wait for zope partition to receive the expected test-runner URL # Promise to wait for zope partition to receive the expected test-runner URL
recipe = slapos.cookbook:check_parameter recipe = slapos.cookbook:check_parameter
value = {{ '${' ~ section_name ~ ':config-test-runner-apache-url-list}' }} value = {{ '${' ~ section_name ~ ':config-test-runner-balancer-url-list}' }}
expected-not-value = not-ready expected-not-value = not-ready
expected-value = expected-value =
path = ${directory:bin}/${:_buildout_section_name_} path = ${directory:bin}/${:_buildout_section_name_}
......
...@@ -523,7 +523,7 @@ command-line-extra = ...@@ -523,7 +523,7 @@ command-line-extra =
--erp5_sql_connection_string '{{ connection_string_list[0] }}' --erp5_sql_connection_string '{{ connection_string_list[0] }}'
--extra_sql_connection_string_list '{{ ','.join(connection_string_list[1:]) }}' --extra_sql_connection_string_list '{{ ','.join(connection_string_list[1:]) }}'
--zserver {{ test_runner_address_list[0][0] ~ ':' ~ test_runner_address_list[0][1] }} --zserver {{ test_runner_address_list[0][0] ~ ':' ~ test_runner_address_list[0][1] }}
--zserver_frontend_url {{ slapparameter_dict['test-runner-apache-url-list'][0] }} --zserver_frontend_url {{ slapparameter_dict['test-runner-balancer-url-list'][0] }}
{% if test_runner_random_activity_priority is not none %} {% if test_runner_random_activity_priority is not none %}
--random_activity_priority={{ test_runner_random_activity_priority }} --random_activity_priority={{ test_runner_random_activity_priority }}
{%- endif %} {%- endif %}
...@@ -540,21 +540,21 @@ environment-extra += ...@@ -540,21 +540,21 @@ environment-extra +=
{% do zserver_address_list.append(ip ~ ':' ~ port) %} {% do zserver_address_list.append(ip ~ ':' ~ port) %}
{% endfor -%} {% endfor -%}
zserver_address_list={{ ','.join(zserver_address_list) }} zserver_address_list={{ ','.join(zserver_address_list) }}
zserver_frontend_url_list={{ ','.join(slapparameter_dict['test-runner-apache-url-list']) }} zserver_frontend_url_list={{ ','.join(slapparameter_dict['test-runner-balancer-url-list']) }}
[promise-test-runner-apache-url-executable] [promise-test-runner-balancer-url-executable]
# promise to wait for apache partition to have returned the parameter # promise to wait for balancer partition to have returned the parameter
recipe = slapos.cookbook:check_parameter recipe = slapos.cookbook:check_parameter
value = {{ slapparameter_dict['test-runner-apache-url-list'] }} value = {{ slapparameter_dict['test-runner-balancer-url-list'] }}
expected-not-value = not-ready expected-not-value = not-ready
path = ${directory:bin}/${:_buildout_section_name_} path = ${directory:bin}/${:_buildout_section_name_}
expected-value = expected-value =
[{{ section("promise-test-runner-apache-url") }}] [{{ section("promise-test-runner-balancer-url") }}]
<= monitor-promise-base <= monitor-promise-base
promise = check_command_execute promise = check_command_execute
name = ${:_buildout_section_name_}.py name = ${:_buildout_section_name_}.py
config-command = ${promise-test-runner-apache-url-executable:path} config-command = ${promise-test-runner-balancer-url-executable:path}
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}
......
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