Skip to content
This repository was archived by the owner on Oct 22, 2019. It is now read-only.

Commit f369aa4

Browse files
committed
Merge pull request #76 from fasaxc/smc-per-host-config
Add DatastoreClient CRUD methods for per-host configuration.
2 parents b76ad04 + 753e67f commit f369aa4

File tree

2 files changed

+84
-4
lines changed

2 files changed

+84
-4
lines changed

calico_containers/pycalico/datastore.py

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
CONFIG_IF_PREF_PATH = CONFIG_PATH + "InterfacePrefix"
4444
HOSTS_PATH = CALICO_V_PATH + "/host/"
4545
HOST_PATH = HOSTS_PATH + "%(hostname)s/"
46+
HOST_CONFIG_PATH = HOST_PATH + "config/"
47+
HOST_CONFIG_KEY_PATH = HOST_CONFIG_PATH + "%(config_param)s"
4648
ORCHESTRATOR_PATH = HOST_PATH + "workload/%(orchestrator_id)s/"
4749
WORKLOAD_PATH = ORCHESTRATOR_PATH + "%(workload_id)s/"
4850
LOCAL_ENDPOINTS_PATH = WORKLOAD_PATH + "endpoint/"
@@ -280,14 +282,63 @@ def create_host(self, hostname, ipv4, ipv6, as_num):
280282
# This is important for Mesos, where the containerized executor process
281283
# needs to exchange messages with the Mesos Slave process running on
282284
# the host.
283-
self.etcd_client.write(host_path +
284-
"config/DefaultEndpointToHostAction", "RETURN")
285+
self.set_per_host_config(hostname, "DefaultEndpointToHostAction",
286+
"RETURN")
285287

286-
# Flag to Felix that the host is created.
287-
self.etcd_client.write(host_path + "config/marker", "created")
288+
# Flag that the host is created.
289+
self.set_per_host_config(hostname, "marker", "created")
288290

289291
return
290292

293+
@handle_errors
294+
def get_per_host_config(self, hostname, config_param):
295+
"""
296+
Get a raw (string) per-host config parameter from etcd.
297+
:param hostname: The name of the host.
298+
:param config_param: The name of the config parameter (e.g.
299+
"LogSeverityFile").
300+
:return: string value or None if config wasn't present.
301+
"""
302+
config_key = HOST_CONFIG_KEY_PATH % {
303+
"hostname": hostname,
304+
"config_param": config_param,
305+
}
306+
try:
307+
return self.etcd_client.read(config_key).value
308+
except EtcdKeyNotFound:
309+
return None
310+
311+
@handle_errors
312+
def set_per_host_config(self, hostname, config_param, value):
313+
"""
314+
Write a raw (string) per-host config parameter to etcd.
315+
:param hostname: The name of the host who's config should be updated.
316+
:param config_param: The name of the parameter (e.g.
317+
"LogSeverityFile").
318+
:param value: The raw string value to set, or None to delete the key.
319+
"""
320+
config_key = HOST_CONFIG_KEY_PATH % {
321+
"hostname": hostname,
322+
"config_param": config_param,
323+
}
324+
if value is not None:
325+
self.etcd_client.write(config_key, value)
326+
else:
327+
try:
328+
self.etcd_client.delete(config_key)
329+
except EtcdKeyNotFound:
330+
pass
331+
332+
@handle_errors
333+
def remove_per_host_config(self, hostname, config_param):
334+
"""
335+
Remove a per-host config parameter.
336+
:param hostname: The name of the host who's config should be updated.
337+
:param config_param: The name of the parameter (e.g.
338+
"LogSeverityFile").
339+
"""
340+
self.set_per_host_config(hostname, config_param, None)
341+
291342
@handle_errors
292343
def remove_host(self, hostname):
293344
"""

calico_containers/tests/unit/datastore_test.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,35 @@ def mock_read(path):
911911
any_order=True)
912912
assert_equal(self.etcd_client.write.call_count, 6)
913913

914+
def test_get_per_host_config_mainline(self):
915+
value = self.datastore.get_per_host_config("hostname", "SomeConfig")
916+
assert_equal(value, self.etcd_client.read.return_value.value)
917+
assert_equal(self.etcd_client.read.mock_calls,
918+
[call("/calico/v1/host/hostname/config/SomeConfig")])
919+
920+
def test_get_per_host_config_not_exist(self):
921+
self.etcd_client.read.side_effect = EtcdKeyNotFound
922+
value = self.datastore.get_per_host_config("hostname", "SomeConfig")
923+
assert_is_none(value)
924+
925+
def test_set_per_host_config_mainline(self):
926+
self.datastore.set_per_host_config("hostname", "SomeConfig", "foo")
927+
assert_equal(self.etcd_client.write.mock_calls,
928+
[call("/calico/v1/host/hostname/config/SomeConfig",
929+
"foo")])
930+
931+
def test_set_per_host_config_none(self):
932+
# This exception should be suppressed
933+
self.etcd_client.delete.side_effect = EtcdKeyNotFound
934+
self.datastore.set_per_host_config("hostname", "SomeConfig", None)
935+
assert_equal(self.etcd_client.delete.mock_calls,
936+
[call("/calico/v1/host/hostname/config/SomeConfig")])
937+
938+
def test_remove_per_host_config_none(self):
939+
self.datastore.remove_per_host_config("hostname", "SomeConfig")
940+
assert_equal(self.etcd_client.delete.mock_calls,
941+
[call("/calico/v1/host/hostname/config/SomeConfig")])
942+
914943
def test_remove_host_mainline(self):
915944
"""
916945
Test remove_host() when the key exists.

0 commit comments

Comments
 (0)