Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

topogen: allocate ipv4 subnets for docker #3840

Merged
merged 1 commit into from
Jul 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions acceptance/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,6 @@ fail() {
exit 1
}

#######################################
# Returns whether this script is running in docker
#######################################
is_running_in_docker() {
cut -d: -f 3 /proc/1/cgroup | grep -q '^/docker/'
}

#######################################
# Return the ip of the container
# Arguments:
Expand Down
1 change: 1 addition & 0 deletions go/integration/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ go_library(
"//go/lib/snet:go_default_library",
"//go/lib/sock/reliable:go_default_library",
"@com_github_opentracing_opentracing_go//:go_default_library",
"@com_github_uber_jaeger_client_go//:go_default_library",
],
)
11 changes: 11 additions & 0 deletions go/integration/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ import (
"context"
"flag"
"fmt"
"net"
"os"
"time"

"github.com/opentracing/opentracing-go"
"github.com/uber/jaeger-client-go"

"github.com/scionproto/scion/go/lib/addr"
"github.com/scionproto/scion/go/lib/env"
Expand Down Expand Up @@ -67,9 +69,18 @@ func addFlags() {

// InitTracer initializes the global tracer and returns a closer function.
func InitTracer(name string) (func(), error) {
agent := fmt.Sprintf("jaeger:%d", jaeger.DefaultUDPSpanServerPort)
c, err := net.DialTimeout("udp", agent, 100*time.Millisecond)
if err != nil {
log.Debug("Jaeger tracer not found, using default", "err", err)
agent = ""
} else if c != nil {
c.Close()
}
cfg := &env.Tracing{
Enabled: true,
Debug: true,
Agent: agent,
}
cfg.InitDefaults()
tr, closer, err := cfg.NewTracer(name)
Expand Down
4 changes: 0 additions & 4 deletions integration/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@ is_docker_be() {
[ -f gen/scion-dc.yml ]
}

is_running_in_docker() {
cut -d: -f 3 /proc/1/cgroup | grep -q '^/docker/'
}

usage() {
echo "Usage: $0: [-b brs]"
exit 1
Expand Down
10 changes: 3 additions & 7 deletions integration/integration_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,9 @@ shutdown() {
fi
}

if is_running_in_docker; then
log "Starting scion (without building)"
./scion.sh run nobuild | grep -v "started" || exit 1
else
log "Starting scion"
./scion.sh run | grep -v "started" || exit 1
fi
log "Starting scion"
./scion.sh run | grep -v "started" || exit 1

log "Scion status:"
./scion.sh status || exit 1
if is_docker_be; then
Expand Down
34 changes: 15 additions & 19 deletions python/topology/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
# limitations under the License.

# Stdlib
import ipaddress
from ipaddress import ip_address, ip_network
import os
import subprocess
import sys
from urllib.parse import urlsplit
from typing import Mapping

# SCION
from python.lib.scion_addr import ISD_AS
from python.topology.net import AddressProxy
from python.topology.net import AddressProxy, NetworkDescription

COMMON_DIR = 'endhost'

Expand Down Expand Up @@ -109,21 +109,23 @@ def split_host_port(addr: str) -> (str, int):


def join_host_port(host: str, port: int) -> str:
ip = ipaddress.ip_address(host)
ip = ip_address(host)
if ip.version == 4:
return '{}:{}'.format(host, port)
return '[{}]:{}'.format(host, port)


def sciond_ip(docker, topo_id, networks):
for i, net in enumerate(networks):
for prog, ip_net in networks[net].items():
def sciond_ip(docker, topo_id, networks: Mapping[ip_network, NetworkDescription]):
for net_desc in networks.values():
for prog, ip_net in net_desc.ip_net.items():
if prog == 'sd%s' % topo_id.file_fmt():
return ip_net.ip
return None


def prom_addr_dispatcher(docker, topo_id, networks, port, name):
def prom_addr_dispatcher(docker, topo_id,
networks: Mapping[ip_network, NetworkDescription],
port, name):
if not docker:
return "[127.0.0.1]:%s" % port
target_name = ''
Expand All @@ -133,9 +135,9 @@ def prom_addr_dispatcher(docker, topo_id, networks, port, name):
target_name = 'sig%s' % topo_id.file_fmt()
else:
target_name = 'disp%s' % topo_id.file_fmt()
for _, net in enumerate(networks):
if target_name in networks[net]:
return '[%s]:%s' % (networks[net][target_name].ip, port)
for net_desc in networks.values():
if target_name in net_desc.ip_net:
return '[%s]:%s' % (net_desc.ip_net[target_name].ip, port)
return None


Expand All @@ -159,14 +161,8 @@ def docker_image(args, image):
return image


def docker_host(in_docker, docker, addr=None):
if in_docker:
# If in-docker we need to know the DOCKER0 IP
addr = os.getenv('DOCKER0', None)
if not addr:
print('DOCKER0 env variable required! Exiting!')
sys.exit(1)
elif docker or not addr:
def docker_host(docker, addr=None):
if docker or not addr:
# Using docker topology or there is no default addr,
# we directly get the DOCKER0 IP
addr = docker_ip()
Expand Down
36 changes: 26 additions & 10 deletions python/topology/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import os
import sys
from io import StringIO
from ipaddress import ip_network
from typing import Mapping

# SCION
from python.lib.defines import (
Expand All @@ -41,6 +43,7 @@
from python.topology.go import GoGenArgs, GoGenerator
from python.topology.jaeger import JaegerGenArgs, JaegerGenerator
from python.topology.net import (
NetworkDescription,
SubnetGenerator,
DEFAULT_NETWORK,
)
Expand Down Expand Up @@ -81,16 +84,17 @@ def _read_defaults(self, network):
Configure default network.
"""
defaults = self.topo_config.get("defaults", {})
self.subnet_gen4 = SubnetGenerator(DEFAULT_NETWORK, self.args.docker, self.args.in_docker)
self.subnet_gen6 = SubnetGenerator(DEFAULT6_NETWORK, self.args.docker, self.args.in_docker)
self.subnet_gen4 = SubnetGenerator(DEFAULT_NETWORK, self.args.docker)
self.subnet_gen6 = SubnetGenerator(DEFAULT6_NETWORK, self.args.docker)
self.default_mtu = defaults.get("mtu", DEFAULT_MTU)

def generate_all(self):
"""
Generate all needed files.
"""
self._ensure_uniq_ases()
topo_dicts, self.networks = self._generate_topology()
topo_dicts, self.all_networks = self._generate_topology()
self.networks = remove_v4_nets(self.all_networks)
self._generate_with_topo(topo_dicts)
self._write_networks_conf(self.networks, NETWORKS_FILE)
self._write_sciond_conf(self.networks, SCIOND_ADDRESSES_FILE)
Expand Down Expand Up @@ -160,7 +164,7 @@ def _generate_docker(self, topo_dicts):
docker_gen.generate()

def _docker_args(self, topo_dicts):
return DockerGenArgs(self.args, topo_dicts, self.networks)
return DockerGenArgs(self.args, topo_dicts, self.all_networks)

def _generate_prom_conf(self, topo_dicts):
args = self._prometheus_args(topo_dicts)
Expand All @@ -179,23 +183,35 @@ def _write_ca_files(self, topo_dicts, ca_files):
for path, value in ca_files[int(isd)].items():
write_file(os.path.join(base, path), value.decode())

def _write_networks_conf(self, networks, out_file):
def _write_networks_conf(self,
networks: Mapping[ip_network, NetworkDescription],
out_file: str):
config = configparser.ConfigParser(interpolation=None)
for i, net in enumerate(networks):
for net, net_desc in networks.items():
sub_conf = {}
for prog, ip_net in networks[net].items():
for prog, ip_net in net_desc.ip_net.items():
sub_conf[prog] = ip_net.ip
config[net] = sub_conf
text = StringIO()
config.write(text)
write_file(os.path.join(self.args.output_dir, out_file), text.getvalue())

def _write_sciond_conf(self, networks, out_file):
def _write_sciond_conf(self, networks: Mapping[ip_network, NetworkDescription], out_file: str):
d = dict()
for i, net in enumerate(networks):
for prog, ip_net in networks[net].items():
for net_desc in networks.values():
for prog, ip_net in net_desc.ip_net.items():
if prog.startswith("sd"):
ia = prog[2:].replace("_", ":")
d[ia] = str(ip_net.ip)
with open(os.path.join(self.args.output_dir, out_file), mode="w") as f:
json.dump(d, f, sort_keys=True, indent=4)


def remove_v4_nets(nets: Mapping[ip_network, NetworkDescription]
) -> Mapping[ip_network, NetworkDescription]:
res = {}
for net, net_desc in nets.items():
if net_desc.name.endswith('_v4'):
continue
res[net] = net_desc
return res
36 changes: 29 additions & 7 deletions python/topology/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# Stdlib
import copy
import os
from ipaddress import ip_network
from typing import Mapping
# External packages
import yaml
# SCION
Expand All @@ -24,18 +26,20 @@
)
from python.topology.common import (
ArgsTopoDicts,
docker_host,
docker_image,
DOCKER_USR_VOL,
sciond_svc_name
)
from python.topology.docker_utils import DockerUtilsGenArgs, DockerUtilsGenerator
from python.topology.net import NetworkDescription
from python.topology.sig import SIGGenArgs, SIGGenerator

DOCKER_CONF = 'scion-dc.yml'


class DockerGenArgs(ArgsTopoDicts):
def __init__(self, args, topo_dicts, networks):
def __init__(self, args, topo_dicts, networks: Mapping[ip_network, NetworkDescription]):
"""
:param object args: Contains the passed command line arguments as named attributes.
:param dict topo_dicts: The generated topo dicts from TopoGenerator.
Expand All @@ -57,7 +61,7 @@ def __init__(self, args):
self.bridges = {}
self.output_base = os.environ.get('SCION_OUTPUT_BASE', os.getcwd())
self.user_spec = os.environ.get('SCION_USERSPEC', '$LOGNAME')
self.prefix = 'scion_docker_' if self.args.in_docker else 'scion_'
self.prefix = 'scion_'

def generate(self):
self._create_networks()
Expand Down Expand Up @@ -89,19 +93,32 @@ def _gen_sig(self):
self.dc_conf = sig_gen.generate()

def _create_networks(self):
for network in self.args.networks:
for elem in self.args.networks[network]:
# first find v4 allocations, those networks don't need to be generated.
v4nets = {}
ignore_nets = []
for network, net_desc in self.args.networks.items():
if network.version == 6:
continue
if net_desc.name.endswith('_v4'):
v4nets[net_desc.name[:-3]] = network
ignore_nets.append(network)

for network, net_desc in self.args.networks.items():
if network in ignore_nets:
continue
for elem in net_desc.ip_net:
if elem not in self.elem_networks:
self.elem_networks[elem] = []
ipv = 'ipv4'
if self.args.networks[network][elem].ip.version == 6:
ip = net_desc.ip_net[elem].ip
if ip.version == 6:
ipv = 'ipv6'
self.elem_networks[elem].append({
'net': str(network),
ipv: self.args.networks[network][elem].ip
ipv: ip
})
# Create docker networks
prefix = 'scnd_' if self.args.in_docker else 'scn_'
prefix = 'scn_'
net_name = "%s%03d" % (prefix, len(self.bridges))
self.bridges[str(network)] = net_name
self.dc_conf['networks'][net_name] = {
Expand All @@ -113,6 +130,9 @@ def _create_networks(self):
'com.docker.network.bridge.name': net_name
}
}
if net_desc.name in v4nets:
v4_net = v4nets[net_desc.name]
self.dc_conf['networks'][net_name]['ipam']['config'].append({'subnet': str(v4_net)})
if network.version == 6:
self.dc_conf['networks'][net_name]['enable_ipv6'] = True

Expand Down Expand Up @@ -178,6 +198,7 @@ def _control_service_conf(self, topo_id, topo, base):
def _dispatcher_conf(self, topo_id, topo, base):
image = 'dispatcher'
base_entry = {
'extra_hosts': ['jaeger:%s' % docker_host(self.args.docker)],
'image': docker_image(self.args, image),
'environment': {
'SU_EXEC_USERSPEC': self.user_spec,
Expand Down Expand Up @@ -216,6 +237,7 @@ def _sciond_conf(self, topo_id, base):
ip = str(net[ipv])
disp_id = 'cs%s-1' % topo_id.file_fmt()
entry = {
'extra_hosts': ['jaeger:%s' % docker_host(self.args.docker)],
'image': docker_image(self.args, 'sciond'),
'container_name': '%ssd%s' % (self.prefix, topo_id.file_fmt()),
'depends_on': [
Expand Down
Loading