All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit 92e7c6fa authored by Kirk Webb's avatar Kirk Webb

Merge branch 'mobile'

Conflicts:
	configure
parents 771111b8 48bf6f8d
......@@ -32,6 +32,7 @@ PELABSUPPORT = @PELABSUPPORT@
PGENISUPPORT = @PROTOGENI_SUPPORT@
ISMAINSITE = @TBMAINSITE@
SPEWFROMOPS = @SPEWFROMOPS@
MOBILESUPPORT = @MOBILESUPPORT@
SYSTEM := $(shell uname -s)
include Makeconf
......@@ -53,7 +54,7 @@ SUBDIRS = \
db assign www @optional_subdirs@ clientside ipod security sensors \
pxe tbsetup account tmcd utils backend tip ipod vis \
sensors os xmlrpc autofs install/newnode_sshkeys \
tools/svn wiki collab/exp-vis node_usage install
tools/svn collab/exp-vis node_usage install
ifeq ($(ISMAINSITE),1)
SUBDIRS += tools/rmanage tools/whol
endif
......@@ -127,9 +128,11 @@ post-install:
@$(MAKE) -C www post-install
ifeq ($(EVENTSYS),1)
@$(MAKE) -C event post-install
endif
ifeq ($(MOBILESUPPORT),1)
@$(MAKE) -C mobile
endif
@$(MAKE) -C tools post-install
@$(MAKE) -C wiki post-install
@$(MAKE) -C collab post-install
@$(MAKE) -C utils post-install
ifeq ($(NODE_USAGE_SUPPORT),1)
......
......@@ -23,6 +23,7 @@
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = @top_builddir@
MOBILESUPPORT = @MOBILESUPPORT@
SUBDIR = $(subst $(TESTBED_SRCDIR)/,,$(SRCDIR))
SYSTEM := $(shell uname -s)
ARCH := $(shell uname -p)
......@@ -34,6 +35,9 @@ SUBDIRS = lib tools os sensors protogeni
ifneq ($(EVENTSYS),0)
SUBDIRS += event
endif
ifeq ($(MOBILESUPPORT),1)
SUBDIRS += mobile
endif
# tmcc should be last as the freenas* install targets mess with the hierarchy
SUBDIRS += tmcc
......
......@@ -622,6 +622,7 @@ ac_includes_default="\
ac_subst_vars='LTLIBOBJS
LIBOBJS
DISTCLEAN_FILES
MOBILESUPPORT
PYTHON_INCLUDE
EGREP
GREP
......@@ -726,6 +727,7 @@ with_TBDEFS
enable_windows
enable_elvin_compat
enable_TPM
enable_mobile
'
ac_precious_vars='build_alias
host_alias
......@@ -1353,6 +1355,7 @@ Optional Features:
--enable-windows[=yes/no] Enable Windows FAT/NTFS support in imagezip [default=no]
--enable-elvin_compat[=yes/no] Include Elvin Hash compat [default=no]
--enable-TPM[=yes/no] Include TPM support [default=no]
--enable-mobile[=yes/no] Enable mobile support (PhantomNet) [default=no]
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
......@@ -4490,6 +4493,34 @@ if test -n ${WINDOWS_KEY_7PRO_X86}; then
winfiles="$winfiles tmcc/cygwinseven/unattend-7pro-x86.xml"
fi
# Mobile networking support
MOBILESUPPORT=0
# Check whether --enable-mobile was given.
if test "${enable_mobile+set}" = set; then :
enableval=$enable_mobile;
fi
if test "$enable_mobile" = "no"; then
MOBILESUPPORT=0;
elif test "$enable_mobile" = "yes"; then
MOBILESUPPORT=1;
fi
if test $MOBILESUPPORT -eq 0; then
mobilefiles=""
else
mobilefiles="mobile/GNUmakefile"
cat >>confdefs.h <<_ACEOF
#define MOBILESUPPORT 1
_ACEOF
fi
outfiles="Makeconf GNUmakefile setversion \
lib/GNUmakefile \
lib/libtb/GNUmakefile \
......@@ -4566,7 +4597,8 @@ outfiles="Makeconf GNUmakefile setversion \
os/imagezip/extfs/GNUmakefile \
$winfiles \
os/imagezip/hashmap/GNUmakefile \
protogeni/GNUmakefile"
protogeni/GNUmakefile \
$mobilefiles"
#
# Do this for easy distclean.
......
......@@ -227,6 +227,27 @@ if test -n ${WINDOWS_KEY_7PRO_X86}; then
winfiles="$winfiles tmcc/cygwinseven/unattend-7pro-x86.xml"
fi
# Mobile networking support
AC_SUBST(MOBILESUPPORT)
MOBILESUPPORT=0
AC_ARG_ENABLE(mobile,
[ --enable-mobile[[=yes/no]] Enable mobile support (PhantomNet) [[default=no]]])
if test "$enable_mobile" = "no"; then
MOBILESUPPORT=0;
elif test "$enable_mobile" = "yes"; then
MOBILESUPPORT=1;
fi
if test $MOBILESUPPORT -eq 0; then
mobilefiles=""
else
mobilefiles="mobile/GNUmakefile"
AC_DEFINE_UNQUOTED(MOBILESUPPORT, 1, [Support mobile networking])
fi
outfiles="Makeconf GNUmakefile setversion \
lib/GNUmakefile \
lib/libtb/GNUmakefile \
......@@ -303,7 +324,8 @@ outfiles="Makeconf GNUmakefile setversion \
os/imagezip/extfs/GNUmakefile \
$winfiles \
os/imagezip/hashmap/GNUmakefile \
protogeni/GNUmakefile"
protogeni/GNUmakefile \
$mobilefiles"
#
# Do this for easy distclean.
......
#
# Copyright (c) 2013-2014 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = @top_builddir@
SUBDIR = $(subst $(TESTBED_SRCDIR)/,,$(SRCDIR))
TB_SBIN_DIR = $(DESTDIR)/usr/testbed/sbin
LIB_DIR = $(DESTDIR)$(CLIENT_BINDIR)
LIBSTUFF = libjsonrpc.pm tbadb_rpc.pm
SBINSTUFF = tbadb_serv
include $(OBJDIR)/Makeconf
all:
include $(TESTBED_SRCDIR)/GNUmakerules
client: $(LIBSTUFF) $(SBINSTUFF)
client-install: client
-mkdir -p $(LIB_DIR) $(TB_SBIN_DIR)
$(INSTALL_PROGRAM) $(SRCDIR)/tbadb_serv $(TB_SBIN_DIR)
$(INSTALL) $(SRCDIR)/libjsonrpc.pm $(LIB_DIR)
$(INSTALL) $(SRCDIR)/tbadb_rpc.pm $(LIB_DIR)
boss-install: $(addprefix $(INSTALL_LIBDIR)/,$(LIBSTUFF))
control-install:
fs-install:
subboss:
subboss-install:
post-install:
clean:
distclean:
mfs:
mfs-install:
frisbee-mfs:
frisbee-mfs-install:
newnode-mfs:
newnode-mfs-install:
#!/usr/bin/perl -w
#
# Copyright (c) 2016 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
package libjsonrpc;
use Exporter;
@ISA = "Exporter";
@EXPORT =
qw ( EncodeCall EncodeResult EncodeError
DecodeRPCData SendRPCData RecvRPCData );
# After package decl.
use English;
use JSON;
use Data::Dumper;
# Constants
my $MAXFID = 100;
# Global variables
our $debug = 0;
my $FID = 0;
my %fid2func = ();
my $PDUBUF = '';
my $PDUBUFSIZ = 10_000;
my $SEPSTR = "\r\n\r\n";
my $MINTMO = 1; # No less than 1 second
my $MAXTMO = 300; # No more than 5 minutes
sub _getNextFID($) {
my ($func) = @_;
my $wrapped = 0;
while (1) {
$FID++;
if (!exists($fid2func{$FID})) {
return $FID;
}
if ($FID > $MAXFID) {
if ($wrapped) {
die "FID wrapped and no free FID slot found!\n";
}
warn "libjsonrpc::GetNextFid: Warning: FID wrapped!\n";
$FID = 1;
$wrapped = 1;
}
}
die "libjsonrpc::GetNextFid: Control should never reach here!";
}
sub EncodeCall($;$) {
my ($func, $args) = @_;
if (!$func) {
warn "libjsonrpc::EncodeCall: No function call specified!\n";
return undef;
}
my $fid = _getNextFID($func);
# We don't check or validate the arguments in any way. That will be
# up to the receiving end to do in context. If they can be JSON encoded,
# all is well from this encoding function's perspective. Also, if
# nothing is passed in for $args, it will be passed along here as undefined
# to the json encoder which will in turn convert it to a JSON 'null'.
warn "libjsonrpc::EncodeCall: encoding '$func'\nArgs:\n" . Dumper($args)
if $debug;
my $json_text = eval { to_json({FID => $fid,
FUNCTION => $func,
ARGS => $args}); };
if ($@) {
warn "Error encoding function call to JSON data: $@\n";
return undef;
}
if (!$json_text) {
warn "libjsonrpc::EncodeCall: Nothing returned by to_json!\n";
return undef;
}
$fid2func{$fid} = $func;
return $json_text;
}
sub EncodeResult($$) {
my ($fid, $results) = @_;
if (!$fid) {
warn "TBDB::EncodeResult: A valid function call ID must be given!";
return undef;
}
# We don't check or validate results in any way. That will be
# up to the receiving end to do in context. If they can be JSON encoded,
# all is well from this encoding function's perspective.
my $json_text = to_json({FID => $fid,
RESULT => $results});
if (!$json_text) {
warn "libjsonrpc::EncodeResult: Nothing returned by to_json!\n";
return undef;
}
return $json_text;
}
sub EncodeError($$;$) {
my ($fid, $code, $message) = @_;
if (!$fid || $fid < 1 || !defined($code)) {
warn "libjsonrpc::EncodeError: Must provide valid FID and code id!\n";
return undef;
}
$message ||= "(No Message)";
my $json_text = to_json({FID => $fid,
ERROR => {CODE => $code, MESSAGE => $message}});
if (!$json_text) {
warn "libjsonrpc::EncodeError: Nothing returned by to_json!\n";
return undef;
}
return $json_text;
}
sub DecodeRPCData($) {
my ($json_text) = @_;
if (!$json_text) {
warn "libjsonrpc::DecodeRPCData: No data to decode!\n";
return undef;
}
my $data = eval { from_json($json_text); };
if ($@) {
warn "Error trying to decode JSON data: $@\n";
return undef;
}
if (ref($data) ne "HASH") {
warn "Did not parse out a hash from JSON data!\n";
return undef;
}
if (!exists($data->{FID})) {
warn "No FID (function ID) found in JSON data!\n";
return undef;
}
my $fid = $data->{FID};
if (exists($data->{FUNCTION})) {
warn "libjsonrpc::DecodeRPCData: Function $data->{FUNCTION} called.\n"
if $debug;
}
elsif (exists($data->{RESULT})) {
if (!exists($fid2func{$fid}) && $fid != -1) {
warn "libjsonrpc::DecodeRPCData: Unknown FID in results: $fid\n";
} else {
warn "libjsonrpc::DecodeRPCData: Results returned for FID $fid ($fid2func{$fid})\n"
if $debug;
delete $fid2func{$fid};
}
}
elsif (exists($data->{ERROR})) {
if (!exists($fid2func{$fid})) {
warn "libjsonrpc::DecodeRPCData: Unknown FID in error: $fid\n";
} else {
warn "libjsonrpc::DecodeRPCData: Error returned for FID $fid ($fid2func{$fid})\n"
if $debug;
delete $fid2func{$fid};
}
}
else {
warn "libjsonrpc::DecodeRPCData: Unidentifiable RPC data!\n";
return undef;
}
return $data;
}
sub SendRPCData($$) {
my ($fh, $encdata) = @_;
if (!$fh) {
warn "libjsonrpc::SendRPCData: Must provide valid filehandle!\n";
return 0;
}
if (!$encdata) {
warn "libjsonrpc::SendRPCData: Must provide data to send!\n";
return 0;
}
warn "libjsonrpc::SendRPCData: sending: $encdata\n"
if $debug;
$encdata .= $SEPSTR;
my $res = eval { print $fh $encdata };
if ($@) {
warn "libjsonrpc::SendRPCData: Error while attempting to send data: $@";
return 0;
}
if (!$res) {
warn "libjsonrpc::SendRPCData: Printing to filehandle failed: $!";
return 0;
}
return 1;
}
sub _getPDU() {
my $index = index($PDUBUF, $SEPSTR);
if ($index == -1) {
warn "libjsonrpc::GetPDU: PDU separator not found in buffer.\n"
if $debug;
return undef;
}
my $retval = substr($PDUBUF, 0, $index);
$PDUBUF = substr($PDUBUF, $index + length($SEPSTR));
return $retval;
}
sub RecvRPCData($$;$) {
my ($fh, $ppdu, $timeout) = @_;
my $PDU;
$timeout = $MAXTMO if (!defined($timeout));
if (!$fh) {
warn "libjsonrpc::RecvRPCData: Must provide valid filehandle!\n";
return 0;
}
if (!$ppdu || ref($ppdu) ne "SCALAR") {
warn "libjsonrpc::RecvRPCData: Must pass in a scalar reference for holding data!\n";
return 0;
}
if ($timeout && ($timeout < $MINTMO || $timeout > $MAXTMO)) {
warn "Timeout is out of bounds ($MINTMO < timeout < $MAXTMO): $timeout\n";
return 0;
}
my $bits = '';
vec($bits, fileno($fh), 1) = 1;
while (!($PDU = _getPDU())) {
my $nready = select($bits, undef, undef, $timeout);
if (!$nready) {
warn "libjsonrpc::RecvRPCData: Timeout while waiting for data!\n"
if $debug;
return -1;
}
warn "libjsonrpc::RecvRPCData: input filehandle has data.\n"
if $debug;
my $nbytes = sysread($fh, $PDUBUF, $PDUBUFSIZ, length($PDUBUF));
if (!defined($nbytes)) {
warn "libjsonrpc::RecvRPCData: Error reading RPC data from file handle: $!\n";
return 0;
}
elsif ($nbytes == 0) {
warn "libjsonrpc::RecvRPCData: Premature EOF?\n"
if $debug;
return 0;
}
}
$$ppdu = $PDU;
return 1;
}
# Mandatory fun
1;
#!/usr/bin/perl -w
use strict;
use English;
use libjsonrpc;
use Data::Dumper;
my $TMPFILE = "/tmp/footest.tmp";
print "Encoding func with single scalar arg\n";
my $json1 = EncodeCall("scalarargfunc", 1);
print "Encoded as: $json1\n\n";
print "Encoding func with no args\n";
my $json2 = EncodeCall("noargfunc");
print "Encoded as: $json2\n\n";
print "Encoding func with array args\n";
my $json3 = EncodeCall("arrayfunc", ["foo","bar","baz"]);
print "Encoded as: $json3\n\n";
print "Encoding func with hash args\n";
my $json4 = EncodeCall("hashfunc", {FOO => 1, BAR => 2});
print "Encoded as: $json4\n\n";
print "Encoding func with bad arguments (circular ref)\n";
my $dee = {};
my $dum = { DEE => $dee };
$dee->{DUM} = $dum;
my $badjson = EncodeCall("badargs", [$dee, $dum]);
if (!$badjson) {
print "No return value\n\n";
} else {
print "Encoded as: $badjson\n\n";
}
print "'Sending' RPC\n";
my $memvar;
open(my $fh, ">", $TMPFILE) or
die "Could not open $TMPFILE for writing!\n";
my $ret = SendRPCData($fh, $json3);
print "Retval: $ret\n";
print "Sent as: ". `cat $TMPFILE` ."\n";
print "'Sending' another RPC same FH\n";
$ret = SendRPCData($fh, $json4);
print "Retval: $ret\n";
print "Sent as: ". `cat $TMPFILE` ."\n";
print "Sending with undefined data arg.\n";
$ret = SendRPCData($fh, undef);
print "Retval: $ret\n\n";
print "Sending with empty data arg.\n";
$ret = SendRPCData($fh, "");
print "Retval: $ret\n\n";
print "Sending to bogus filehandle.\n";
my $bogus = "asdf";
$ret = SendRPCData($bogus, $json1);
print "Retval: $ret\n\n";
print "Receiving from $TMPFILE!\n";
close $fh;
open ($fh, "<", $TMPFILE) or
die "Could not open $TMPFILE for reading!\n";
my $data1 = RecvRPCData($fh);
print "Received: $data1\n";
print "Receiving again from $TMPFILE...\n";
my $data2 = RecvRPCData($fh);
print "Received: $data2\n";
print "Decoding first read from $TMPFILE.\n";
my $dec1 = DecodeRPCData($data1);
print "Decoded as: ". Dumper($dec1);
print "Decoding second read from $TMPFILE.\n";
my $dec2 = DecodeRPCData($data2);
print "Decoded as: ". Dumper($dec2);
print "Receiving from STDIN...\n";
my $count = 0;
do {
my $data = RecvRPCData(*STDIN, 10);
if (!$data) {
print "No data received.\n";
} elsif ( $data =~ /^-1$/) {
print "Timeout!\n";
} else {
print "Received data: $data\n";
print "Attemping to decode:\n";
my $decoded = DecodeRPCData($data);
if (!$decoded) {
print "Nothing decoded!\n";
} else {
print "Data decoded as: ". Dumper($data);
}
}
$count++;
} while ($count < 10);
close($fh);
print "Done\n";
#!/usr/bin/perl -w
#
# Copyright (c) 2016 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or