Commit e68f9b5f authored by David Johnson's avatar David Johnson

Integrate support for shared Docker hosts reusing subnets.

Allowing vnode experiments running on shared nodes to share IPv4 subnets
is a natural thing in Emulab; not so in Docker.  This is the Emulab side
of that fix.

The Docker side relies on modifications to Docker (see
https://gitlab.flux.utah.edu/emulab/moby/commits/emulab) to add a real
Layer 2 mode to the bridge and macvlan drivers, so that Docker doesn't
require IPv4 configuration of the bridge; and so that it allows Layer
2-only bridges to have overlapping IP subnets.  Normally it does not
allow the latter because it expects that any network might be
routable/reachable by any other network.
parent 80107326
......@@ -802,8 +802,8 @@ $METHODS{'network_create_bridge'} = {
'gateway' => "The new network's gateway IP address",
'brname' => "The existing bridge name that should be used to build the new network atop" }
};
sub network_create_bridge($$$$;$) {
my ($self,$name,$cidr,$gateway,$brname) = @_;
sub network_create_bridge($$$$;$$) {
my ($self,$name,$cidr,$gateway,$brname,$arghashref) = @_;
my $headers = HTTP::Headers->new();
$headers->header("Content-Type" => "application/json");
......@@ -816,6 +816,17 @@ sub network_create_bridge($$$$;$) {
if (defined($brname)) {
$data->{"Options"} = { "com.docker.network.bridge.name" => $brname };
}
if (defined($arghashref) && ref($arghashref) eq 'HASH') {
require Hash::Merge;
if ($self->debug()) {
print STDERR "DEBUG: pre-merge args = ".Dumper($data)."\n";
print STDERR "DEBUG: pre-merge arghashref = ".Dumper($arghashref)."\n";
}
$data = Hash::Merge::merge($data,$arghashref);
if ($self->debug()) {
print STDERR "DEBUG: merged args = ".Dumper($data)."\n";
}
}
return $self->_post("/networks/create",$headers,encode_json($data));
}
......@@ -828,8 +839,8 @@ $METHODS{'network_create_macvlan'} = {
'gateway' => "The new network's gateway IP address",
'basedev' => "The existing macvlan device name that should be used to build the new network atop" }
};
sub network_create_macvlan($$$$;$) {
my ($self,$name,$cidr,$gateway,$basedev) = @_;
sub network_create_macvlan($$$$;$$) {
my ($self,$name,$cidr,$gateway,$basedev,$arghashref) = @_;
my $headers = HTTP::Headers->new();
$headers->header("Content-Type" => "application/json");
......@@ -842,6 +853,17 @@ sub network_create_macvlan($$$$;$) {
if (defined($basedev)) {
$data->{"Options"} = { "parent" => $basedev };
}
if (defined($arghashref) && ref($arghashref) eq 'HASH') {
require Hash::Merge;
if ($self->debug()) {
print STDERR "DEBUG: pre-merge args = ".Dumper($data)."\n";
print STDERR "DEBUG: pre-merge arghashref = ".Dumper($arghashref)."\n";
}
$data = Hash::Merge::merge($data,$arghashref);
if ($self->debug()) {
print STDERR "DEBUG: merged args = ".Dumper($data)."\n";
}
}
return $self->_post("/networks/create",$headers,encode_json($data));
}
......
......@@ -724,8 +724,10 @@ sub ensureDockerInstalled()
#
# Check which docker this is.
#
if (-e "/usr/share/docker.io/EMULAB.md") {
my $rc = system('grep -q PrivatePoolId `which dockerd`');
if ($rc == 0) {
$ISOURDOCKER = 1;
TBDebugTimeStamp("init: ISOURDOCKER=1");
}
}
else {
......@@ -778,8 +780,10 @@ sub ensureDockerInstalled()
#
# Check which docker this is.
#
if (-e "/usr/share/docker-ce/EMULAB.md") {
my $rc = system('grep -q PrivatePoolId `which dockerd`');
if ($rc == 0) {
$ISOURDOCKER = 1;
TBDebugTimeStamp("init: ISOURDOCKER=1");
}
}
......@@ -1428,8 +1432,10 @@ sub init($)
#
# Check which docker this is.
#
if (-e "/usr/share/docker.io/EMULAB.md") {
my $rc = system('grep -q PrivatePoolId `which dockerd`');
if ($rc == 0) {
$ISOURDOCKER = 1;
TBDebugTimeStamp("init: ISOURDOCKER=1");
}
return 0;
......@@ -2523,9 +2529,17 @@ sub rootPreConfigNetwork($$$$)
TBDebugTimeStamp("checking existence of docker network $k");
($code,$content,$resp) = getClient()->network_inspect($k);
if ($code) {
my $ourdocker_extra_args = undef;
if ($ISOURDOCKER) {
$ourdocker_extra_args = {
"Options" => { "com.docker.network.bridge.layer2_mode"
=> "true" },
"IPAM" => { "Options" => { "PrivatePoolId" => $k } },
};
}
TBDebugTimeStamp("creating docker network $k");
($code,$content,$resp) = getClient()->network_create_bridge(
$k,$cidr,$gw,$k);
$k,$cidr,$gw,$k,$ourdocker_extra_args);
goto bad
if ($code);
}
......
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