Commit f5a5b0e4 authored by Elijah Grubb's avatar Elijah Grubb

Resolved libvnode_docker conflict

parents 6ef666cd 0bf7e0b3
......@@ -32,7 +32,9 @@
"howfull": 100,
"url": "http://docs.cloudlab.us/hardware.html#%28part._cloudlab-wisconsin%29",
"children": [ { "name": "c220g1", "size": 30, "howfull": 3, "url": "http://docs.cloudlab.us/hardware.html#%28part._cloudlab-wisconsin%29" },
{ "name": "c220g2", "size": 163, "howfull": 3, "url": "http://docs.cloudlab.us/hardware.html#%28part._cloudlab-wisconsin%29" } ]
{ "name": "c220g2", "size": 163, "howfull": 3, "url": "http://docs.cloudlab.us/hardware.html#%28part._cloudlab-wisconsin%29" },
{ "name": "c220g5", "size": 225, "howfull": 3, "url": "http://docs.cloudlab.us/hardware.html#%28part._cloudlab-wisconsin%29" },
{ "name": "c240g5", "size": 32, "howfull": 3, "url": "http://docs.cloudlab.us/hardware.html#%28part._cloudlab-wisconsin%29" } ]
}
]
}
......@@ -293,6 +293,8 @@ if [ -f /etc/emulab/version ]; then
fi
echo "# Result variables:"
echo ""
echo "TAG=$tag"
echo "TAG=$tag"
echo "MINTAG=$mintag"
echo "DIST=$dist"
......
#!/usr/bin/perl
#
# Copyright (c) 2017 University of Utah and the Flux Group.
# Copyright (c) 2017, 2018 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -38,11 +38,11 @@ my $VNODESETUP = "$BINDIR/vnodesetup";
sub usage()
{
print STDOUT "" .
"Usage: create-docker-image [-d <level>] [-c] -R <registry> -r <repository> -t <tag>" .
"Usage: create-docker-image [-d <level>] [-c] -i <imageid> -R <registry> -r <repository> -t <tag>" .
" <vnodeid>\n";
exit(-1);
}
my $optlist = "cd:R:r:t:u:p:";
my $optlist = "cd:R:r:t:u:p:i:";
my $filename;
if ($UID != 0) {
......@@ -56,17 +56,20 @@ $| = 1;
# Need this for predicates.
use libsetup;
use libtmcc;
use libvnode_docker;
use libgenvnode;
#use libvnode;
use libutil;
use dockerclient;
use JSON::PP;
use Data::Dumper;
#
# No configure vars.
#
my $vnodeid;
my $imageid;
my ($registry,$repo,$tag,$user,$pass);
my $usecli = 0;
my $debug = 0;
......@@ -79,6 +82,9 @@ my %options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = $options{"d"};
}
if (defined($options{"R"})) {
$registry = $options{"R"};
}
......@@ -97,6 +103,23 @@ if (defined($options{"t"})) {
else {
die("No tag (-t) supplied!");
}
if (defined($options{"i"})) {
$imageid = $options{"i"};
if ($debug) {
print STDERR "DEBUG: using imageid $imageid for events\n";
}
}
else {
print STDERR "WARNING: imageid not supplied; events may be incorrect!\n";
# Assume the repo/tag stuff looks like <proj>/<group>/<imagename>;
# munge that into <proj>/<imagename> and append <tag>.
my @sn = split('/',$repo);
$imageid = $sn[0] . "/" . $sn[@sn-1] . ":$tag";
if ($debug) {
print STDERR "DEBUG: munged repo/tag into imageid $imageid;" .
" using that for events\n";
}
}
if (defined($options{"u"})) {
$user = $options{"u"};
}
......@@ -112,9 +135,6 @@ else {
if (defined($options{"c"})) {
$usecli = 1;
}
if (defined($options{"d"})) {
$debug = $options{"d"};
}
$vnodeid = shift(@ARGV);
if (!defined($vnodeid) || $vnodeid eq '') {
print STDERR "ERROR: no vnodeid specified!\n";
......@@ -130,22 +150,42 @@ if ($debug) {
TBDebugTimeStampsOn();
}
libsetup_setvnodeid($vnodeid);
my %vnconfig = ();
getgenvnodeconfig(\%vnconfig);
my $vnode_ip = $vnconfig{'CTRLIP'};
#
# Maybe send progress events as we upload images. For now, we don't do
# this, since the path of event from node to boss doesn't really exist;
# instead, we write debug messages that our caller (ssh from boss) can
# parse to handle the incremental image size updates.
#
my $sendevents = 0;
if ($sendevents) {
eval "use event";
if ($@) {
$sendevents = 0;
print STDERR "WARNING: cannot load event lib; not sending events!\n";
}
}
#
# First, try to login to the registry with user/pass.
#
my $i = 10;
my $code;
my ($code,$content,$resp);
while ($i > 0) {
if ($usecli) {
system("docker login -p '$pass' -u '$user' $registry");
$code = $?;
}
else {
($code,) = $client->registry_auth($registry,$user,$pass);
($code,$content) = $client->registry_auth($registry,$user,$pass);
}
last
if ($code == 0);
print STDERR "ERROR: failed to login to registry $registry ($code);".
print STDERR "ERROR: failed to login to registry $registry ($code, $content);".
" sleeping and trying again...\n";
sleep(4);
$i -= 1;
......@@ -190,6 +230,17 @@ if ($status ne VNODE_STATUS_STOPPED()) {
exit(1);
}
#
# Try to setup imaging status events.
#
my ($boss_name,$boss_ip) = tmccbossinfo();
if ($sendevents) {
EventRegister("event-server",16505);
if ($debug) {
print STDERR "DEBUG: sendevents: $boss_ip\n";
}
}
#
# (Locally) commit the image.
#
......@@ -198,12 +249,12 @@ if ($usecli) {
system("docker commit $vnodeid $fullimagename");
}
else {
my ($code,$content,$resp) = $client->container_commit(
($code,$content,$resp) = $client->container_commit(
$vnodeid,"$registry/$repo",$tag);
$? = $code;
}
if ($?) {
print STDERR "ERROR: failed to commit image $fullimagename for container $vnodeid; aborting!\n";
print STDERR "ERROR: failed to commit image $fullimagename for container $vnodeid: $content\n";
system("docker logout $registry")
if ($usecli);
exit(1);
......@@ -214,30 +265,76 @@ if ($initstatus ne VNODE_STATUS_STOPPED()) {
system("docker start $vnodeid");
}
else {
my ($code,$content,$resp) = $client->container_start($vnodeid);
($code,$content,$resp) = $client->container_start($vnodeid);
$? = $code;
}
if ($?) {
print STDERR "WARNING: error restarting container $vnodeid; ignoring!\n";
print STDERR "WARNING: error restarting container $vnodeid ($code, $content); ignoring!\n";
}
}
else {
print STDERR "WARNING: not restarting previously stopped container $vnodeid\n";
}
sub sizeToMB($) {
if ($_[0] =~ /^([\d.]+)([gmkGMK]*)([bB])$/) {
my $num = $1 * 1.0;
if ($3 eq 'b') {
$num /= 8;
}
if ($2 eq 'g' || $2 eq 'G') {
$num *= 1024;
}
elsif ($2 eq 'k' || $2 eq 'K') {
$num /= 1024;
}
return $num;
}
return undef;
}
#
# Get the size of each layer so we can send an event for
# already-existing layers.
#
my %layer_size = ();
($code,$content,$resp) = $client->image_history("$registry/$repo:$tag");
if ($debug) {
print "DEBUG: history: " . Dumper($content) . "\n";
}
foreach my $h (@{$content->[0]}) {
next
if (!exists($h->{"Id"}) || !exists($h->{"Size"}));
my $size = $h->{"Size"};
if ($h->{"Id"} =~ /^([\w\d]+):([\w\d]+)$/) {
$layer_size{$2} = $size;
}
}
if ($debug) {
print "DEBUG: history layer sizes: " . Dumper(%layer_size) . "\n";
}
# Push the image and logout.
$i = 10;
my $success = 0;
my %pushed_size = ();
my %event_tuple = ( 'host' => "event-server",
'objtype' => 'IMAGESTATUS',
'objname' => $vnode_ip,
'eventtype' => "$imageid" );
while ($i > 0) {
if ($usecli) {
system("docker push $fullimagename");
}
else {
my ($code,$content,$resp) = $client->image_push(
($code,$content,$resp) = $client->image_push(
$fullimagename,undef,$user,$pass,
sub {
eval {
my $json = decode_json($_[0]);
if ($debug) {
print "DEBUG: progress: " . Dumper($json) . "\n";
}
if (exists($json->{"id"})) {
print $json->{"id"}.": ".$json->{"status"};
if (exists($json->{"progress"})) {
......@@ -248,6 +345,69 @@ while ($i > 0) {
elsif (exists($json->{"status"})) {
print $json->{"status"}."\n";
}
#
# NB: we are all setup to fake the events for
# already pushed layers, but we can't correlate the
# ids in the progress reports below with the layers
# we found in the image history above where we
# extracted the size; and these events don't mention
# the size. This ID mismatch is very, very
# annoying, but nothing I can do.
#
# So note that after we finish the push, we send one
# final event that is the total size of the image.
#
if (exists($json->{"status"})
&& ($json->{"status"} =~ /Layer already exists/i
|| $json->{"status"} eq 'Pushed')) {
my $aeid = $json->{"id"};
foreach my $layer_id (keys(%layer_size)) {
if ($layer_id =~ /^$aeid/) {
$pushed_size{$aeid} = $layer_size{$layer_id};
my $total = 0;
map { $total += $_ } values(%pushed_size);
if ($sendevents) {
$total /= (1024 * 1024);
my $nsref = { 'SIZE' => "".int($total) };
EventSendNotificationStrings(
\%event_tuple,$nsref);
if ($debug) {
print STDERR "DEBUG: sent event ".
Dumper(%event_tuple) . "(" .
Dumper($nsref) . ")\n";
}
}
else {
print "PUSHPROGRESS: $total bytes\n";
}
}
}
}
elsif (exists($json->{"status"})
&& $json->{"status"} eq 'Pushing'
&& exists($json->{"progressDetail"})) {
$pushed_size{$json->{"id"}} = \
$json->{"progressDetail"}->{"current"};
my $total = 0;
map { $total += $_ } values(%pushed_size);
if ($sendevents) {
$total /= (1024 * 1024);
my $nsref = { 'SIZE' => "".int($total) };
EventSendNotificationStrings(
\%event_tuple,$nsref);
if ($debug) {
print STDERR "DEBUG: sent event ".
Dumper(%event_tuple) . "(" .
Dumper($nsref) . ")\n";
}
}
else {
print "PUSHPROGRESS: $total bytes\n";
}
}
};
if ($@) {
print $_[0];
......@@ -256,10 +416,27 @@ while ($i > 0) {
$? = $code;
}
if ($? == 0) {
my $total = 0;
map { $total += $_ } values(%layer_size);
if ($sendevents) {
$total /= (1024 * 1024);
my $nsref = { 'SIZE' => $total };
EventSendNotificationStrings(
\%event_tuple,$nsref);
if ($debug) {
print STDERR "DEBUG: sent event ".
Dumper(%event_tuple) . "(" .
Dumper($nsref) . ")\n";
}
}
else {
print "PUSHPROGRESS: $total bytes\n";
}
$success = 1;
last;
}
print STDERR "ERROR: failed to push $fullimagename; sleeping and trying again...\n";
print STDERR "ERROR: failed to push $fullimagename ($code, $content); sleeping and trying again...\n";
sleep(4);
$i -= 1;
}
......
......@@ -1008,6 +1008,9 @@ sub getDockerNetMemberIds($)
if ($code) {
return undef;
}
if (!ref($content) eq 'HASH') {
$content = $content->[0];
}
if (!exists($content->{"Containers"})) {
return ();
}
......@@ -2769,6 +2772,16 @@ sub vnodeCreate($$$$)
push(@{$args{"HostConfig"}{"Binds"}},
"$mntdir/vmname:/var/emulab/boot/vmname:ro");
#
# Tell the clientside to use the gzip'd versions of ltmap and
# ltpmap; if we don't use these, on multi-thousand node topos, they
# suck up too much space in the host.
#
open(FD,">$mntdir/ltmap-gzip");
close(FD);
push(@{$args{"HostConfig"}{"Binds"}},
"$mntdir/ltmap-gzip:/etc/emulab/ltmap-gzip:ro");
#
# Tell the inside clientside which event server to use. NB: we do
# this as an read-only mount because the container removes it on
......@@ -4034,6 +4047,7 @@ sub analyzeImage($$)
my $output;
my @outlines;
my ($code,$json,$resp,$retval);
my $iid;
TBDebugTimeStamp("analyzing image $image...");
......@@ -4051,6 +4065,7 @@ sub analyzeImage($$)
else {
$jstate = $json;
}
$iid = $jstate->{'Id'};
$jstate = $jstate->{'Config'};
if (exists($jstate->{'Cmd'})) {
......@@ -4075,6 +4090,27 @@ sub analyzeImage($$)
$rethash->{DOCKER_USER} = $jstate->{'User'};
}
}
my $needunlock = 0;
if (defined($iid)) {
if (! -f "/vms/contexts/analyze-$iid") {
if (TBScriptLock("analyze-$iid",
TBSCRIPTLOCK_INTERRUPTIBLE(),
1800) != TBSCRIPTLOCK_OKAY()) {
fatal("Could not get analyze-$iid lock for $image analysis!");
}
TBDebugTimeStamp(" got image analysis lock analyze-$iid for $image")
if ($lockdebug);
$needunlock = 1;
}
if (-f "/vms/contexts/analyze-$iid") {
TBDebugTimeStamp("not running analysis script for image $image;".
" already in /vms/contexts/analyze-$iid\n");
open(FD,"/vms/contexts/analyze-$iid");
@outlines = <FD>;
close(FD);
goto outlines;
}
}
TBDebugTimeStamp("running analysis script for image $image...");
my $args = {
......@@ -4089,9 +4125,19 @@ sub analyzeImage($$)
sub { $buf .= $_[0]; });
if ($code) {
warn("failed to run analysis script container $tmpname for $image");
TBScriptUnlock()
if ($needunlock);
return $code;
}
TBDebugTimeStamp("analyze.sh output:\n$buf");
open(FD,">/vms/contexts/analyze-$iid");
print FD $buf;
close(FD);
@outlines = split("\n",$buf);
outlines:
TBScriptUnlock()
if ($needunlock);
for my $res (@outlines) {
if ($res =~ /^[a-zA-Z0-9_]*=[^=]*$/) {
chomp($res);
......
......@@ -211,7 +211,7 @@ $wire = Interface::Wire->LookupAny($node_id1, $card1, $port1);
if (defined($wire)) {
fatal("Wire using interface two already exists: $wire\n");
}
$wire = Interface::Wire->LookupAny($node_id1, $card2, $port2);
$wire = Interface::Wire->LookupAny($node_id2, $card2, $port2);
if (defined($wire)) {
fatal("Wire using interface two already exists: $wire\n");
}
......
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