mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 09:02:00 +00:00
PoC
This commit is contained in:
parent
dde915681c
commit
cedddf6fa4
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
FROM alpine:3.18
|
FROM alpine:3.18
|
||||||
RUN apk add --no-cache -U iproute2 \
|
RUN apk add --no-cache -U iproute2 \
|
||||||
&& for bin in iptables iptables-restore iptables-save; \
|
&& for bin in \
|
||||||
|
iptables iptables-restore iptables-save \
|
||||||
|
ip6tables ip6tables-restore ip6tables-save; \
|
||||||
do ln -sf xtables-nft-multi "/sbin/$bin"; \
|
do ln -sf xtables-nft-multi "/sbin/$bin"; \
|
||||||
done
|
done
|
||||||
|
@ -3,6 +3,7 @@ import subprocess
|
|||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
import docker
|
import docker
|
||||||
|
import ipaddress
|
||||||
|
|
||||||
|
|
||||||
class PartitionManager:
|
class PartitionManager:
|
||||||
@ -26,23 +27,74 @@ class PartitionManager:
|
|||||||
self._check_instance(instance)
|
self._check_instance(instance)
|
||||||
|
|
||||||
self._add_rule(
|
self._add_rule(
|
||||||
{"source": instance.ip_address, "destination_port": 2181, "action": action}
|
{
|
||||||
|
"source": instance.ipv4_address,
|
||||||
|
"destination_port": 2181,
|
||||||
|
"action": action,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
self._add_rule(
|
self._add_rule(
|
||||||
{"destination": instance.ip_address, "source_port": 2181, "action": action}
|
{
|
||||||
|
"destination": instance.ipv4_address,
|
||||||
|
"source_port": 2181,
|
||||||
|
"action": action,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if instance.ipv6_address:
|
||||||
|
self._add_rule(
|
||||||
|
{
|
||||||
|
"source": instance.ipv6_address,
|
||||||
|
"destination_port": 2181,
|
||||||
|
"action": action,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self._add_rule(
|
||||||
|
{
|
||||||
|
"destination": instance.ipv6_address,
|
||||||
|
"source_port": 2181,
|
||||||
|
"action": action,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def dump_rules(self):
|
def dump_rules(self):
|
||||||
return _NetworkManager.get().dump_rules()
|
v4 = _NetworkManager.get().dump_rules()
|
||||||
|
v6 = _NetworkManager.get().dump_v6_rules()
|
||||||
|
|
||||||
|
return v4 + v6
|
||||||
|
|
||||||
def restore_instance_zk_connections(self, instance, action="DROP"):
|
def restore_instance_zk_connections(self, instance, action="DROP"):
|
||||||
self._check_instance(instance)
|
self._check_instance(instance)
|
||||||
|
|
||||||
self._delete_rule(
|
self._delete_rule(
|
||||||
{"source": instance.ip_address, "destination_port": 2181, "action": action}
|
{
|
||||||
|
"source": instance.ipv4_address,
|
||||||
|
"destination_port": 2181,
|
||||||
|
"action": action,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
self._delete_rule(
|
self._delete_rule(
|
||||||
{"destination": instance.ip_address, "source_port": 2181, "action": action}
|
{
|
||||||
|
"destination": instance.ipv4_address,
|
||||||
|
"source_port": 2181,
|
||||||
|
"action": action,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if instance.ipv6_address:
|
||||||
|
self._delete_rule(
|
||||||
|
{
|
||||||
|
"source": instance.ipv6_address,
|
||||||
|
"destination_port": 2181,
|
||||||
|
"action": action,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self._delete_rule(
|
||||||
|
{
|
||||||
|
"destination": instance.ipv6_address,
|
||||||
|
"source_port": 2181,
|
||||||
|
"action": action,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def partition_instances(self, left, right, port=None, action="DROP"):
|
def partition_instances(self, left, right, port=None, action="DROP"):
|
||||||
@ -59,16 +111,36 @@ class PartitionManager:
|
|||||||
rule["destination_port"] = port
|
rule["destination_port"] = port
|
||||||
return rule
|
return rule
|
||||||
|
|
||||||
|
def create_rule_v6(src, dst):
|
||||||
|
rule = {
|
||||||
|
"source": src.ipv6_address,
|
||||||
|
"destination": dst.ipv6_address,
|
||||||
|
"action": action,
|
||||||
|
}
|
||||||
|
if port is not None:
|
||||||
|
rule["destination_port"] = port
|
||||||
|
return rule
|
||||||
|
|
||||||
self._add_rule(create_rule(left, right))
|
self._add_rule(create_rule(left, right))
|
||||||
self._add_rule(create_rule(right, left))
|
self._add_rule(create_rule(right, left))
|
||||||
|
|
||||||
|
if left.ipv6_address and right.ipv6_address:
|
||||||
|
self._add_rule(create_rule_v6(left, right))
|
||||||
|
self._add_rule(create_rule_v6(right, left))
|
||||||
|
|
||||||
def add_network_delay(self, instance, delay_ms):
|
def add_network_delay(self, instance, delay_ms):
|
||||||
self._add_tc_netem_delay(instance, delay_ms)
|
self._add_tc_netem_delay(instance, delay_ms)
|
||||||
|
|
||||||
def heal_all(self):
|
def heal_all(self):
|
||||||
while self._iptables_rules:
|
while self._iptables_rules:
|
||||||
rule = self._iptables_rules.pop()
|
rule = self._iptables_rules.pop()
|
||||||
|
|
||||||
|
if self._is_ipv6_rule(rule):
|
||||||
|
_NetworkManager.get().delete_ip6tables_rule(**rule)
|
||||||
|
else:
|
||||||
_NetworkManager.get().delete_iptables_rule(**rule)
|
_NetworkManager.get().delete_iptables_rule(**rule)
|
||||||
|
# _NetworkManager.get().delete_iptables_rule(**rule)
|
||||||
|
# _NetworkManager.get().delete_ip6tables_rule(**rule)
|
||||||
|
|
||||||
while self._netem_delayed_instances:
|
while self._netem_delayed_instances:
|
||||||
instance = self._netem_delayed_instances.pop()
|
instance = self._netem_delayed_instances.pop()
|
||||||
@ -90,11 +162,28 @@ class PartitionManager:
|
|||||||
if instance.ip_address is None:
|
if instance.ip_address is None:
|
||||||
raise Exception("Instance + " + instance.name + " is not launched!")
|
raise Exception("Instance + " + instance.name + " is not launched!")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _is_ipv6_rule(rule):
|
||||||
|
is_ipv6 = False
|
||||||
|
|
||||||
|
if "source" in rule:
|
||||||
|
is_ipv6 = ipaddress.ip_address(rule["source"]).version == 6
|
||||||
|
if "destination" in rule:
|
||||||
|
is_ipv6 = ipaddress.ip_address(rule["source"]).version == 6
|
||||||
|
|
||||||
|
return is_ipv6
|
||||||
|
|
||||||
def _add_rule(self, rule):
|
def _add_rule(self, rule):
|
||||||
|
if self._is_ipv6_rule(rule):
|
||||||
|
_NetworkManager.get().add_ip6tables_rule(**rule)
|
||||||
|
else:
|
||||||
_NetworkManager.get().add_iptables_rule(**rule)
|
_NetworkManager.get().add_iptables_rule(**rule)
|
||||||
self._iptables_rules.append(rule)
|
self._iptables_rules.append(rule)
|
||||||
|
|
||||||
def _delete_rule(self, rule):
|
def _delete_rule(self, rule):
|
||||||
|
if self._is_ipv6_rule(rule):
|
||||||
|
_NetworkManager.get().delete_ip6tables_rule(**rule)
|
||||||
|
else:
|
||||||
_NetworkManager.get().delete_iptables_rule(**rule)
|
_NetworkManager.get().delete_iptables_rule(**rule)
|
||||||
self._iptables_rules.remove(rule)
|
self._iptables_rules.remove(rule)
|
||||||
|
|
||||||
@ -155,15 +244,29 @@ class _NetworkManager:
|
|||||||
cmd.extend(self._iptables_cmd_suffix(**kwargs))
|
cmd.extend(self._iptables_cmd_suffix(**kwargs))
|
||||||
self._exec_run(cmd, privileged=True)
|
self._exec_run(cmd, privileged=True)
|
||||||
|
|
||||||
|
def add_ip6tables_rule(self, **kwargs):
|
||||||
|
cmd = ["ip6tables-legacy", "--wait", "-I", "DOCKER-USER", "1"]
|
||||||
|
cmd.extend(self._iptables_cmd_suffix(**kwargs))
|
||||||
|
self._exec_run(cmd, privileged=True)
|
||||||
|
|
||||||
def delete_iptables_rule(self, **kwargs):
|
def delete_iptables_rule(self, **kwargs):
|
||||||
cmd = ["iptables", "--wait", "-D", "DOCKER-USER"]
|
cmd = ["iptables", "--wait", "-D", "DOCKER-USER"]
|
||||||
cmd.extend(self._iptables_cmd_suffix(**kwargs))
|
cmd.extend(self._iptables_cmd_suffix(**kwargs))
|
||||||
self._exec_run(cmd, privileged=True)
|
self._exec_run(cmd, privileged=True)
|
||||||
|
|
||||||
|
def delete_ip6tables_rule(self, **kwargs):
|
||||||
|
cmd = ["ip6tables-legacy", "--wait", "-D", "DOCKER-USER"]
|
||||||
|
cmd.extend(self._iptables_cmd_suffix(**kwargs))
|
||||||
|
self._exec_run(cmd, privileged=True)
|
||||||
|
|
||||||
def dump_rules(self):
|
def dump_rules(self):
|
||||||
cmd = ["iptables", "-L", "DOCKER-USER"]
|
cmd = ["iptables", "-L", "DOCKER-USER"]
|
||||||
return self._exec_run(cmd, privileged=True)
|
return self._exec_run(cmd, privileged=True)
|
||||||
|
|
||||||
|
def dump_v6_rules(self):
|
||||||
|
cmd = ["ip6tables-legacy", "-L", "DOCKER-USER"]
|
||||||
|
return self._exec_run(cmd, privileged=True)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def clean_all_user_iptables_rules():
|
def clean_all_user_iptables_rules():
|
||||||
for i in range(1000):
|
for i in range(1000):
|
||||||
@ -178,6 +281,20 @@ class _NetworkManager:
|
|||||||
+ " iterations, last error: "
|
+ " iterations, last error: "
|
||||||
+ str(res.stderr)
|
+ str(res.stderr)
|
||||||
)
|
)
|
||||||
|
break
|
||||||
|
|
||||||
|
for i in range(1000):
|
||||||
|
iptables_iter = i
|
||||||
|
# when rules will be empty, it will return error
|
||||||
|
res = subprocess.run("ip6tables-legacy --wait -D DOCKER-USER 1", shell=True)
|
||||||
|
|
||||||
|
if res.returncode != 0:
|
||||||
|
logging.info(
|
||||||
|
"All ip6tables rules cleared, "
|
||||||
|
+ str(iptables_iter)
|
||||||
|
+ " iterations, last error: "
|
||||||
|
+ str(res.stderr)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -244,7 +361,7 @@ class _NetworkManager:
|
|||||||
def _ensure_container(self):
|
def _ensure_container(self):
|
||||||
if self._container is None or self._container_expire_time <= time.time():
|
if self._container is None or self._container_expire_time <= time.time():
|
||||||
image_name = "clickhouse/integration-helper:" + os.getenv(
|
image_name = "clickhouse/integration-helper:" + os.getenv(
|
||||||
"DOCKER_HELPER_TAG", "latest"
|
"DOCKER_HELPER_TAG", ""
|
||||||
)
|
)
|
||||||
for i in range(5):
|
for i in range(5):
|
||||||
if self._container is not None:
|
if self._container is not None:
|
||||||
|
Loading…
Reference in New Issue
Block a user