Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • alex_orange/emulab-devel
  • hakasapl/emulab-devel
  • cecchet/emulab-devel
  • srirams/emulab-devel
  • chuck/emulab-devel
  • crd/emulab-devel
  • kwebb/emulab-devel
  • moate/emulab-devel
  • grubb/emulab-devel
  • nasir/emulab-devel
  • asydney/emulab-devel
  • kdownie/emulab-devel
  • wvdemeer/emulab-devel
  • anilmr/emulab-devel
  • bvermeul/emulab-devel
  • emulab/emulab-devel
16 results
Show changes
Commits on Source (18298)
VERSION export-subst
# Files that already had DOS-style line endings and those
# that require them should be added to the list below.
clientside/sensors/slothd/idlemon.vbs -crlf
clientside/tmcc/cygwinseven/SetupComplete.cmd -crlf
clientside/tmcc/cygwinseven/unattend-x86.xml.in -crlf
clientside/tmcc/cygwinxp/cygwin-tcsh.bat -crlf
clientside/tmcc/cygwinxp/resolv.conf -crlf
clientside/tmcc/cygwinxp/site-lisp/cygwin-mount.el -crlf
clientside/tmcc/cygwinxp/site-lisp/site-start.el -crlf
clientside/tmcc/cygwinxp/sysprep.inf -crlf
delay/linux/iptables_mods/iptables-1.3.6-imq.diff -crlf
hyperviewer/hv.dsp -crlf
hyperviewer/hv.dsw -crlf
hyperviewer/hypview.bat -crlf
hyperviewer/hypviewer/examples/mfc/h3.cpp -crlf
hyperviewer/hypviewer/examples/mfc/h3Doc.cpp -crlf
hyperviewer/hypviewer/examples/mfc/h3Doc.h -crlf
hyperviewer/hypviewer/examples/mfc/h3.dsp -crlf
hyperviewer/hypviewer/examples/mfc/h3.dsw -crlf
hyperviewer/hypviewer/examples/mfc/h3.h -crlf
hyperviewer/hypviewer/examples/mfc/h3.rc -crlf
hyperviewer/hypviewer/examples/mfc/H3View.cpp -crlf
hyperviewer/hypviewer/examples/mfc/H3View.h -crlf
hyperviewer/hypviewer/examples/mfc/main.cpp -crlf
hyperviewer/hypviewer/examples/mfc/MainFrm.cpp -crlf
hyperviewer/hypviewer/examples/mfc/MainFrm.h -crlf
hyperviewer/hypviewer/examples/mfc/main.h -crlf
hyperviewer/hypviewer/examples/mfc/res/h3.rc2 -crlf
hyperviewer/hypviewer/examples/mfc/Resource.h -crlf
hyperviewer/hypviewer/examples/mfc/StdAfx.cpp -crlf
hyperviewer/hypviewer/examples/mfc/StdAfx.h -crlf
hyperviewer/win32/sets.py -crlf
image-test/tests/linkdelay/nsfile.ns -crlf
image-test/tests/traffic-gen/nsfile.ns -crlf
mote/powermon/powerMeasure/exceptions.cpp -crlf
mote/powermon/powerMeasure/exceptions.h -crlf
mote/powermon/powerMeasure/main.cpp -crlf
mote/powermon/powerMeasure/Makefile -crlf
mote/powermon/powerMeasure/powerMeasure.cpp -crlf
mote/powermon/powerMeasure/powerMeasure.h -crlf
pelab/magent/Command.h -crlf
pelab/magent/CommandInput.h -crlf
pelab/magent/CommandOutput.h -crlf
pelab/magent/Connection.cc -crlf
pelab/magent/KernelTcp.cc -crlf
pelab/magent/lib.cc -crlf
pelab/magent/main.cc -crlf
pelab/magent/SensorList.h -crlf
pelab/stub/lookup.cc -crlf
pelab/stub/stub.h -crlf
protogeni/demo/speed-test/Main.as -crlf
protogeni/demo/speed-test.php -crlf
protogeni/demo/src/AbstractNodes.as -crlf
protogeni/demo/src/ActiveNodes.as -crlf
protogeni/demo/src/AddLinkClip.as -crlf
protogeni/demo/src/com/mattism/http/xmlrpc/MethodFault.as -crlf
protogeni/demo/src/ComponentView.as -crlf
protogeni/demo/src/Console.as -crlf
protogeni/demo/src/CustomCellRenderer.as -crlf
protogeni/demo/src/Link.as -crlf
protogeni/demo/src/ListItem.as -crlf
protogeni/demo/src/Node.as -crlf
protogeni/demo/src/Queue.as -crlf
protogeni/demo/src/QueueNode.as -crlf
protogeni/demo/src/RemoveLinkClip.as -crlf
protogeni/demo/src/RequestReleaseTicket.as -crlf
protogeni/demo/src/RequestSliceEmbedding.as -crlf
protogeni/demo/src/RequestSliverCreate.as -crlf
protogeni/demo/src/RequestSliverDestroy.as -crlf
protogeni/demo/src/RequestSliverStart.as -crlf
protogeni/demo/src/RequestSliverUpdate.as -crlf
protogeni/demo/src/SimpleNodeClip.as -crlf
protogeni/demo/src/SliceWait.as -crlf
tbsetup/ipassign/dre/prepass/pistream.h -crlf
tbsetup/ipassign/dre/prepass/postream.h -crlf
tbsetup/ipassign/etc/autocheck.conf -crlf
tbsetup/plab/libdslice/xmlrpcserver.py -crlf
www/csshover.htc -crlf
www/cssmenu.css -crlf
www/cssmenu-new.css -crlf
www/emulab-mime-winxp.reg -crlf
www/hardware-cmuemlab.html -crlf
www/js/mootools-core.js -crlf
www/js/mootools-tips.js -crlf
www/js/treemap.js -crlf
www/rdp-mime-winxp.c -crlf
www/rdp-mime-winxp.pl -crlf
www/ssh-mime-windows.pl -crlf
www/ssh-mime-winxp.c -crlf
www/ssh-mime-winxp.pl -crlf
www/style.css -crlf
www/style-new.css -crlf
.merge-build
clientside/tmcc/cygwinseven/unattend-7pro-x86.xml.in
extendCMV
\ No newline at end of file
[submodule "protogeni/rspec-geni"]
path = protogeni/rspec-geni
url = git://git-public.flux.utah.edu/geni-rspec.git
......@@ -2,6 +2,16 @@ configure
autoconf/config.guess
autoconf/config.sub
autoconf/install.sh
clientside/configure
clientside/autoconf/config.guess
clientside/autoconf/config.sub
clientside/autoconf/install.sh
clientside/os/imagezip/fat
clientside/os/imagezip/ntfs/liblocale
clientside/lib/event/event_wrap*
clientside/tmcc/cygwinxp/site-lisp
clientside/tmcc/freebsd/init
clientside/tmcc/plab
os/shd
www/cvsweb
robots/vmcd/camera_data/output_camera*
......@@ -40,3 +50,8 @@ LGPL-COPYING
AGPL-COPYING
TODO.plab
MOVED-TO-WIKI
VERSION
protogeni/flack/js/forge
protogeni/flack/src/com/hurlant
protogeni/flack/src/com/mattism
protogeni/protogeniflash/src/com/mattism
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2009 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2000-2021 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/>.
#
# }}}
#
# Testbed Makefile
#
......@@ -13,6 +30,9 @@ DISTCLEAN_FILES = @DISTCLEAN_FILES@
EVENTSYS = @EVENTSYS@
PELABSUPPORT = @PELABSUPPORT@
PGENISUPPORT = @PROTOGENI_SUPPORT@
ISMAINSITE = @TBMAINSITE@
SPEWFROMOPS = @SPEWFROMOPS@
MOBILESUPPORT = @MOBILESUPPORT@
SYSTEM := $(shell uname -s)
include Makeconf
......@@ -25,19 +45,27 @@ include Makeconf
# @optional_subdirs@ (has event)
# ipod os security sensors
# Then things that only depend on stuff we've done:
# pxe tbsetup tmcd utils backend www tip capture vis
# pxe tbsetup tmcd utils backend www tip vis
# Then things that depend on stuff we just did:
#
ifeq ($(STANDALONE_CLEARINGHOUSE),0)
SUBDIRS = lib db assign www @optional_subdirs@ ipod security sensors \
pxe tbsetup account tmcd utils backend tip capture ipod vis \
sensors os xmlrpc install/newnode_sshkeys mote tools/whol \
tools/svn wiki bugdb collab tools/rmanage protogeni node_usage
SUBDIRS = \
clientside/lib \
db assign www @optional_subdirs@ clientside ipod security sensors \
pxe tbsetup account tmcd utils wbstore backend ipod vis \
sensors os xmlrpc autofs install/newnode_sshkeys \
tools/svn collab/exp-vis node_usage install
ifeq ($(ISMAINSITE),1)
SUBDIRS += tools/whol
endif
ifeq ($(PGENISUPPORT),1)
SUBDIRS += protogeni apt powder
endif
else
SUBDIRS = db tbsetup account protogeni
endif
all: all-subdirs
all: all-subdirs just-builddirs
#
# We used to statically link our event agents. We no longer do this, but
......@@ -58,17 +86,35 @@ endif
#
# For installation on boss node
#
boss-install: install-schemacheck install-sitevarscheck install-dbfillcheck \
install-genischemacheck install-subdirs install-mkdirs \
boss-install: install-checks \
install-subdirs install-mkdirs \
install-setbuildinfo
@echo "Boss node installed!"
#
# Same target, with the install-schemacheck dependency omitted
#
# Same target, with the checks omitted
boss-install-force: install-subdirs install-mkdirs install-setbuildinfo
@echo "Boss node installed!"
# Skip only the schema checks, but do the other checks.
boss-install-noschemacheck: install-updatecheck \
install-sitevarscheck install-dbfillcheck \
install-genischemacheck install-subdirs install-mkdirs \
install-setbuildinfo
# Skip the update check.
boss-install-noupdatecheck: install-schemacheck \
install-sitevarscheck install-dbfillcheck \
install-genischemacheck install-subdirs install-mkdirs \
install-setbuildinfo
# Only the checks:
install-checks: \
install-updatecheck \
install-schemacheck \
install-sitevarscheck \
install-dbfillcheck install-genischemacheck
@echo "Installation checks completed!"
clrhouse-install: install-subdirs install-mkdirs
@echo "CleaingHouse code installed!"
......@@ -83,10 +129,10 @@ post-install:
ifeq ($(EVENTSYS),1)
@$(MAKE) -C event post-install
endif
@$(MAKE) -C mote post-install
ifeq ($(MOBILESUPPORT),1)
@$(MAKE) -C mobile
endif
@$(MAKE) -C tools post-install
@$(MAKE) -C wiki post-install
@$(MAKE) -C bugdb post-install
@$(MAKE) -C collab post-install
@$(MAKE) -C utils post-install
ifeq ($(NODE_USAGE_SUPPORT),1)
......@@ -102,38 +148,39 @@ ops-install:
-chmod 770 $(INSTALL_TOPDIR)/log/mysql
-chown mysql $(INSTALL_TOPDIR)/log/mysql
-chgrp mysql $(INSTALL_TOPDIR)/log/mysql
-mkdir -p $(INSTALL_TOPDIR)/log/logfiles
-chmod 777 $(INSTALL_TOPDIR)/log/logfiles
@$(MAKE) -C rc.d control-install
@$(MAKE) -C tbsetup control-install
@$(MAKE) -C security control-install
@$(MAKE) -C tip control-install
# @$(MAKE) -C os control-install
@$(MAKE) -C db control-install
@$(MAKE) -C tbsetup control-install
@$(MAKE) -C utils control-install
@$(MAKE) -C lib control-install
@$(MAKE) -C clientside control-install
ifeq ($(EVENTSYS),1)
@$(MAKE) -C event control-install
endif
@$(MAKE) -C sensors control-install
@$(MAKE) -C xmlrpc control-install
@$(MAKE) -C tmcd control-install
@$(MAKE) -C account control-install
ifeq ($(PELABSUPPORT),1)
@$(MAKE) -C pelab control-install
endif
fs-install:
@$(MAKE) -C rc.d fs-install
@$(MAKE) -C tbsetup fs-install
@$(MAKE) -C clientside fs-install
@$(MAKE) -C sensors fs-install
opsfs-install: ops-install fs-install
@echo "Combined ops/fs install done."
install-mkdirs:
-mkdir -p $(INSTALL_TOPDIR)/db
-mkdir -p $(INSTALL_TOPDIR)/locks
-mkdir -p $(INSTALL_TOPDIR)/log
-mkdir -p $(INSTALL_TOPDIR)/log/mysql
-mkdir -p $(INSTALL_TOPDIR)/etc
-mkdir -p $(INSTALL_TOPDIR)/www
-mkdir -p $(INSTALL_TOPDIR)/suidbin
-mkdir -p $(INSTALL_TOPDIR)/ssl
-chmod 770 $(INSTALL_TOPDIR)/ssl
ifeq ($(STANDALONE_CLEARINGHOUSE),0)
......@@ -152,14 +199,18 @@ ifeq ($(STANDALONE_CLEARINGHOUSE),0)
-chmod 777 $(INSTALL_TOPDIR)/exparchive/Archive
-mkdir -p $(INSTALL_TOPDIR)/images
-chmod 775 $(INSTALL_TOPDIR)/images
-ln -s /usr/testbed/bin/nse $(INSTALL_TOPDIR)/bin
-ln -sf /usr/testbed/bin/nse $(INSTALL_TOPDIR)/bin
endif
just-builddirs:
@$(MAKE) -C rc.d all
@$(MAKE) -C apache all
tipserv-install:
-mkdir -p $(INSTALL_TOPDIR)/log/tiplogs
-mkdir -p $(INSTALL_TOPDIR)/etc
@$(MAKE) -C tip tipserv-install
@$(MAKE) -C capture tipserv-install
@$(MAKE) -C clientside/tip tipserv-install
@$(MAKE) -C clientside/os/capture tipserv-install
@$(MAKE) -C tbsetup tipserv-install
client-mkdirs:
......@@ -167,48 +218,48 @@ client-mkdirs:
-mkdir -p $(DESTDIR)$(CLIENT_MANDIR)
client:
@$(MAKE) -C lib/libtb client
ifeq ($(EVENTSYS),1)
@$(MAKE) -C event client
endif
@$(MAKE) -C clientside client
@$(MAKE) -C os client
ifneq ($(SYSTEM),CYGWIN_NT-5.1)
@$(MAKE) -C capture client
@$(MAKE) -C tip client
@$(MAKE) -C tools client
endif
@$(MAKE) -C sensors client
@$(MAKE) -C tmcd client
client-install: client client-mkdirs
ifeq ($(EVENTSYS),1)
@$(MAKE) -C event client-install
endif
@$(MAKE) -C clientside client-install
@$(MAKE) -C os client-install
ifneq ($(SYSTEM),CYGWIN_NT-5.1)
@$(MAKE) -C capture client-install
@$(MAKE) -C tip client-install
@$(MAKE) -C tools client-install
endif
@$(MAKE) -C sensors client-install
@$(MAKE) -C tmcd client-install
subboss:
@$(MAKE) -C clientside subboss
@$(MAKE) -C tbsetup subboss
@$(MAKE) -C db subboss
@$(MAKE) -C os subboss
@$(MAKE) -C utils subboss
subboss-install: subboss
@$(MAKE) -C clientside subboss-install
@$(MAKE) -C tbsetup subboss-install
@$(MAKE) -C os subboss-install
@$(MAKE) -C utils subboss-install
@$(MAKE) -C db subboss-install
@$(MAKE) -C rc.d subboss-install
@$(MAKE) -C dhcpd subboss-install
# Hack: this should probably be done by a subboss-install
# script, but there isn't a huge need for that yet
@rm -f $(INSTALL_RCDIR)/isc-dhcpd
TARBALLDESTDIR = /var/tmp/emulab-client
client-tarball:
@if [ `id -u` -ne 0 ]; then \
echo '*** Must run as root!'; \
false; \
fi
@if [ -d "$(TARBALLDESTDIR)" ]; then \
echo "$(TARBALLDESTDIR) already exists."; \
echo "Remove it and try again."; \
false; \
fi
echo "Building and installing client-side in $(TARBALLDESTDIR)..."
DESTDIR=$(TARBALLDESTDIR) $(MAKE) client-install
echo "Creating tarball..."
tar czf emulab-client.tar.gz -C $(TARBALLDESTDIR) .
@$(MAKE) -C clientside client-tarball
client-src-tarball:
@rm -f emulab-client-src.tar.gz
tar clzf emulab-client-src.tar.gz -C clientside
# This is not finished yet.
client-shadow-rpm:
-$(RM) -rf rpmbuild
mkdir -p rpmbuild/SOURCES rpmbuild/SRPMS
$(CP) emulab-client-src.tar.gz rpmbuild/SOURCES
$(RPM) -v -bs --nodeps --define='_topdir $(TOPDIR)/rpmbuild' \
clientside/shadow.spec
destdircheck:
@if [ -z "$(DESTDIR)" ]; then \
......@@ -227,64 +278,97 @@ mfsoscheck:
fi
mfs: mfsoscheck
@$(MAKE) -C os mfs
@$(MAKE) -C sensors mfs
@$(MAKE) -C tmcd mfs
@$(MAKE) -C clientside mfs
mfs-nostatic: mfsoscheck
@NOSTATIC=1 $(MAKE) -C os mfs
@NOSTATIC=1 $(MAKE) -C sensors mfs
@NOSTATIC=1 $(MAKE) -C tmcd mfs
@NOSTATIC=1 $(MAKE) -C clientside mfs
mfs-install: destdircheck mfs client-mkdirs
@$(MAKE) -C os mfs-install
@$(MAKE) -C sensors mfs-install
@$(MAKE) -C tmcd mfs-install
@$(MAKE) -C clientside mfs-install
mfs-nostatic-install: destdircheck mfs-nostatic client-mkdirs
@$(MAKE) -C os mfs-install
@$(MAKE) -C sensors mfs-install
@$(MAKE) -C tmcd mfs-install
@$(MAKE) -C clientside mfs-install
frisbee-mfs: mfsoscheck
@$(MAKE) -C cdrom/groklilo client
@$(MAKE) -C os frisbee-mfs
@$(MAKE) -C tmcd frisbee-mfs
@$(MAKE) -C clientside frisbee-mfs
frisbee-mfs-nostatic: mfsoscheck
@NOSTATIC=1 $(MAKE) -C cdrom/groklilo client
@NOSTATIC=1 $(MAKE) -C os frisbee-mfs
@NOSTATIC=1 $(MAKE) -C tmcd frisbee-mfs
@NOSTATIC=1 $(MAKE) -C clientside frisbee-mfs
frisbee-mfs-install: destdircheck frisbee-mfs
@CLIENT_BINDIR=/etc/testbed $(MAKE) -e -C cdrom/groklilo client-install
@$(MAKE) -C os frisbee-mfs-install
@$(MAKE) -C tmcd frisbee-mfs-install
@$(MAKE) -C clientside frisbee-mfs-install
frisbee-mfs-nostatic-install: destdircheck frisbee-mfs-nostatic
@CLIENT_BINDIR=/etc/testbed $(MAKE) -e -C cdrom/groklilo client-install
@$(MAKE) -C os frisbee-mfs-install
@$(MAKE) -C tmcd frisbee-mfs-install
@$(MAKE) -C clientside frisbee-mfs-install
newnode-mfs: mfsoscheck
@$(MAKE) -C clientside newnode-mfs
newnode-mfs-nostatic: mfsoscheck
@NOSTATIC=1 $(MAKE) -C clientside newnode-mfs
newnode-mfs-install: destdircheck newnode-mfs client-mkdirs
@$(MAKE) -C clientside newnode-mfs-install
newnode-mfs-nostatic-install: destdircheck newnode-mfs-nostatic client-mkdirs
@$(MAKE) -C clientside newnode-mfs-install
cdboot: mfsoscheck client
@echo "CD/Dongle files built"
cdboot-install: destdircheck cdboot
@$(MAKE) -C cdrom client-install
@$(MAKE) -C tmcd/freebsd6 cdboot-install
@$(MAKE) -C clientside/tmcc/freebsd6 cdboot-install
flashboot: mfsoscheck client
@echo "Flash dongle files built"
flashboot-install: destdircheck flashboot
@$(MAKE) -C tmcd/freebsd6 cdboot-install
@$(MAKE) -C clientside/tmcc/freebsd6 cdboot-install
@$(MAKE) -C os frisbee-mfs-install
@$(MAKE) -C flash client-install
@$(MAKE) -C clientside frisbee-mfs-install
#
# A check to see if this is a 'real' install. Kinda hacky, but as far as I can
# tell, you can't put ifeq()'s inside of targets
#
ifeq ($(TBROOT),/usr/testbed)
UPDATETESTBED= @cd $(OBJDIR)/install && perl update-testbed
else
UPDATETESTBED= @echo "Skipping update check, since prefix isn't /usr/testbed"
endif
ifeq ($(ISMAINSITE),1)
update-testbed: update-testbed-nostop
else
update-testbed: update-testbed-install
endif
update-testbed-install:
@echo "Updating the testbed ..."
$(UPDATETESTBED) -i -s
update-testbed-noinstall:
@echo "Updating the testbed ..."
$(UPDATETESTBED)
update-testbed-nostop:
@echo "Updating the testbed ..."
$(UPDATETESTBED) -i
update-testbed-force:
@echo "Updating the testbed in force mode ..."
$(UPDATETESTBED) -f
ifeq ($(TBROOT),/usr/testbed)
UPDATECHECK= @cd $(OBJDIR)/install && perl update-testbed -v
else
UPDATECHECK= @echo "Skipping update checks, since prefix isn't /usr/testbed"
endif
install-updatecheck:
@echo "Checking to see if updates need to be run"
$(UPDATECHECK)
ifeq ($(TBROOT),/usr/testbed)
SCHEMACHECK= cd $(OBJDIR)/db && perl schemacheck
else
......@@ -327,6 +411,19 @@ ifeq ($(PGENISUPPORT),1)
endif
@echo "Done"
BRANCHCHECK=
BRANCHECHO= @echo "Skipping branch check since not the Mothership"
ifeq ($(ISMAINSITE),1)
ifeq ($(TBROOT),/usr/testbed)
BRANCHCHECK= cd $(SRCDIR) && \
git status --porcelain -s -b | head -1 | grep -q -s current
BRANCHECHO= @echo "Checking to make sure you are on the mothership branch"
endif
endif
install-branchcheck:
$(BRANCHECHO)
$(BRANCHCHECK)
# We use separate src and obj trees in Emulab, so the traditional distclean to
# clean "made" files from a mingled source-and-obj tree is unnecessary.
# However, this may be useful if you mistakenly configure and make a src tree.
......@@ -334,6 +431,25 @@ clean: clean-subdirs
distclean: distclean-subdirs
rm -f Makeconf GNUmakefile config.h config.status config.cache config.log
rm -f $(DISTCLEAN_FILES)
#
# Be careful, do not run these unless you are updating your installation
# with a new IP subnet or domain name.
#
boss-updateip-clean: clean
@$(MAKE) -C rc.d clean
@$(MAKE) -C apache clean
@$(MAKE) -C named clean
@$(MAKE) -C dhcpd clean
ops-updateip-clean: clean
@$(MAKE) -C rc.d clean
@$(MAKE) -C apache clean
update-rcd:
@$(MAKE) -C rc.d all
@$(MAKE) -C rc.d install
#
# Here's a different approch to recover from just configure problems. It cleans
# all files from an obj tree that have a corresponding .in file in the src tree.
......@@ -341,10 +457,45 @@ undo-configure:
find $SRCDIR -name '*.in' -a -not -name configure.in | \
sed -e "s;$SRCDIR;$OBJDIR;" -e 's;[.]in$;;' | xargs rm -f
elabinelab:
#
# XXX a "temporary" hack for scripts that were evolving fast.
# We didn't want to have to remake the client image whenever we changed these.
# They are copied over to the embryonic boss and ops during setup.
#
elabinelab-scripts:
mkdir -p $(INSTALL_TOPDIR)/etc
cp -f $(SRCDIR)/clientside/tmcc/freebsd/mkextrafs.pl $(INSTALL_TOPDIR)/etc/
cp -f $(SRCDIR)/clientside/tmcc/common/config/rc.mkelab $(INSTALL_TOPDIR)/etc/
ifeq ($(SPEWFROMOPS),1)
elabinelab-nogit: elabinelab-scripts
-mkdir -p /share/emulab
rm -f /share/emulab/emulab-src.tar.gz
tar czf /share/emulab/emulab-src.tar.gz -C $(SRCDIR) --exclude=.git .
elabinelab-git: elabinelab-scripts
-mkdir -p /share/emulab
rm -f /share/emulab/emulab-src.tar.gz
(cd $(SRCDIR); \
git archive HEAD > /share/emulab/emulab-src.tar)
tar rf /share/emulab/emulab-src.tar -C $(SRCDIR) \
--exclude=.git protogeni/rspec-geni
gzip /share/emulab/emulab-src.tar
else
elabinelab-nogit: elabinelab-scripts
-mkdir -p $(INSTALL_TOPDIR)/src
rm -f $(INSTALL_TOPDIR)/src/emulab-src.tar.gz
tar czf $(INSTALL_TOPDIR)/src/emulab-src.tar.gz -C $(SRCDIR) .
tar czf $(INSTALL_TOPDIR)/src/emulab-src.tar.gz -C $(SRCDIR) --exclude=.git .
elabinelab-git: elabinelab-scripts
-mkdir -p $(INSTALL_TOPDIR)/src
rm -f $(INSTALL_TOPDIR)/src/emulab-src.tar.gz
(cd $(SRCDIR); \
git archive HEAD > $(INSTALL_TOPDIR)/src/emulab-src.tar)
tar rf $(INSTALL_TOPDIR)/src/emulab-src.tar -C $(SRCDIR) \
--exclude=.git protogeni/rspec-geni
gzip $(INSTALL_TOPDIR)/src/emulab-src.tar
endif
# How to recursively descend into subdirectories to make general
# targets such as `all'.
......@@ -355,7 +506,10 @@ elabinelab:
# By default, make any target by descending into subdirectories.
%: %-subdirs ;
.PHONY: post-install install-mkdirs clrhouse-install install
.PHONY: post-install install-mkdirs clrhouse-install install \
boss-install-noupdatecheck boss-install-noschemacheck \
boss-install-force update-testbed update-testbed-install \
update-testbed-noinstall update-testbed-nostop
# Get rid of a bunch of nasty built-in implicit rules.
.SUFFIXES:
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2006 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2000-2012, 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/>.
#
# }}}
# Get rid of a bunch of nasty built-in implicit rules,
# to avoid bogus circular dependencies and make things go faster.
......@@ -36,29 +53,76 @@ $(INSTALL_ETCDIR)/%: %
-mkdir -p $(INSTALL_ETCDIR)
$(INSTALL_DATA) $< $@
$(addprefix $(INSTALL_SBINDIR)/, $(SETUID_SBIN_SCRIPTS)): $(INSTALL_SBINDIR)/%: %
$(addprefix $(INSTALL_SBINDIR)/, $(SETUID_SBIN_PROGS)): $(INSTALL_SBINDIR)/%: %
echo "Installing (setuid) $<"
-mkdir -p $(INSTALL_SBINDIR)
$(SUDO) $(INSTALL) -o root -m 4755 $< $@
$(addprefix $(INSTALL_BINDIR)/, $(SETUID_BIN_SCRIPTS)): $(INSTALL_BINDIR)/%: %
$(addprefix $(INSTALL_BINDIR)/, $(SETUID_BIN_PROGS)): $(INSTALL_BINDIR)/%: %
echo "Installing (setuid) $<"
-mkdir -p $(INSTALL_BINDIR)
$(SUDO) $(INSTALL) -o root -m 4755 $< $@
$(addprefix $(INSTALL_LIBEXECDIR)/, $(SETUID_LIBX_SCRIPTS)): $(INSTALL_LIBEXECDIR)/%: %
$(addprefix $(INSTALL_LIBEXECDIR)/, $(SETUID_LIBX_PROGS)): $(INSTALL_LIBEXECDIR)/%: %
echo "Installing (setuid) $<"
-mkdir -p $(INSTALL_LIBEXECDIR)
$(SUDO) $(INSTALL) -o root -m 4755 $< $@
$(addprefix $(INSTALL_SBINDIR)/, $(SETUID_SBIN_SCRIPTS)): $(INSTALL_SBINDIR)/%: % $(INSTALL_SUIDDIR)/%
echo "Installing (link to wrapper) $<"
-mkdir -p $(INSTALL_SBINDIR)
-rm -f $@
ln -s $(INSTALL_LIBEXECDIR)/runsuid $@
$(addprefix $(INSTALL_BINDIR)/, $(SETUID_BIN_SCRIPTS)): $(INSTALL_BINDIR)/%: % $(INSTALL_SUIDDIR)/%
echo "Installing (link to wrapper) $<"
-mkdir -p $(INSTALL_BINDIR)
-rm -f $@
ln -s $(INSTALL_LIBEXECDIR)/runsuid $@
$(addprefix $(INSTALL_LIBEXECDIR)/, $(SETUID_LIBX_SCRIPTS)): $(INSTALL_LIBEXECDIR)/%: % $(INSTALL_SUIDDIR)/%
echo "Installing (link to wrapper) $<"
-mkdir -p $(INSTALL_LIBEXECDIR)
-rm -f $@
ln -s $(INSTALL_LIBEXECDIR)/runsuid $@
# Special libexec rule for scripts invoked by suexec (cannot be a symlink)
$(addprefix $(INSTALL_LIBEXECDIR)/, $(SETUID_SUEXEC_SCRIPTS)): $(INSTALL_LIBEXECDIR)/%: % $(INSTALL_SUIDDIR)/%
echo "Installing (hard link to wrapper) $<"
-mkdir -p $(INSTALL_LIBEXECDIR)
-rm -f $@
ln $(INSTALL_LIBEXECDIR)/runsuid $@
$(INSTALL_SUIDDIR)/%: %
echo "Installing (real script) $<"
-mkdir -p $(INSTALL_SUIDDIR)
$(SUDO) $(INSTALL_PROGRAM) $< $@
CFLAGS += $(LOCALCFLAGS)
clean:
distclean: clean
# This is to avoid warnings about duplicate targets.
distclean: default-clean
default-clean:
rm -f GNUmakefile
# This is to avoid warnings about duplicate targets.
default-install-notusing:
ifeq ($(ISMAINSITE),1)
ifeq ($(TBROOT),/usr/testbed)
(cd $(SRCDIR) ; \
git status --porcelain -s -b | head -1 | grep -q -s current)
else
/usr/bin/true
endif
else
/usr/bin/true
endif
#install: default-install
#
# Where to find source files.
# Using specific patterns instead of the catch-all VPATH variable
......@@ -97,7 +161,7 @@ vpath % $(SRCDIR) $(MOSTLY_SRCDIRS)
#
# Rules to regen configure written files.
#
%: %.in
%: %.in $(OBJDIR)/config.status
@echo "Regenerating $@"
cd $(OBJDIR) && CONFIG_FILES=$(SUBDIR)/$@ ./config.status
......@@ -117,3 +181,25 @@ check: $(TESTS)
fi \
done
endif
ifeq ($(MERGE_BUILD),1)
.PRECIOUS: ${SRCDIR}/*
#
# I really want to say something like:
# ${TESTBED_SRCDIR}/.merged: $(wildcard ${OBJDIR}/${MERGE_BUILD_SANDBOX}/${SUBDIR}/*)
# but that causes problems if one the prereq. has a rule for it (such
# as when both GNUmakefile and GNUmakefile.in exist in the source tree),
# thus I do the equivalent manually
#
newest=$(shell ls -rtd "${OBJDIR}/${MERGE_BUILD_SANDBOX}/${SUBDIR}/"* "${TESTBED_SRCDIR}/.merged" | tail -n 1)
ifneq ($(newest),${TESTBED_SRCDIR}/.merged)
${TESTBED_SRCDIR}/.merged:
cd ${TESTBED_SRCDIR} && utils/merge-build sync
.PHONY: ${TESTBED_SRCDIR}/.merged
else
${TESTBED_SRCDIR}/.merged:
endif
${SRCDIR}/*: ${TESTBED_SRCDIR}/.merged
endif
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2009 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2000-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/>.
#
# }}}
#
# Most of the configure-substitution magic is done here.
# All the other makefiles in the NodeOS include
......@@ -27,6 +44,7 @@ export JAR = @JAR@
prefix = @prefix@
exec_prefix = @exec_prefix@
ISMAINSITE = @TBMAINSITE@
TBROOT = @prefix@
TBDEFS = @TBDEFS@
TBDBNAME = @TBDBNAME@
......@@ -62,6 +80,7 @@ INSTALL_LIBEXECDIR = @libexecdir@
INSTALL_ETCDIR = @sysconfdir@
INSTALL_INCDIR = @includedir@
INSTALL_WWWDIR = @exec_prefix@/www
INSTALL_SUIDDIR = @exec_prefix@/suidbin
INSTALL_RCDIR = @INSTALL_RCDIR@
INSTALL_APACHE_CONFIG = @INSTALL_APACHE_CONFIG@
......@@ -83,6 +102,11 @@ ELVIN_COMPAT = @ELVIN_COMPAT@
HAVE_MEZZANINE = @HAVE_MEZZANINE@
GTK_CONFIG = @GTK_CONFIG@
BRAINSTEM_DIR = @BRAINSTEM_DIR@
WITH_EMULAB = @WITH_EMULAB@
OPSVM_ENABLE = @OPSVM_ENABLE@
OPSVM_MOUNTPOINT= @OPSVM_MOUNTPOINT@
APACHE_VERSION = @APACHE_VERSION@
APACHE_START_COMMAND = @APACHE_START_COMMAND@
host_cpu = @host_cpu@
......@@ -90,3 +114,11 @@ HAVE_ULXMLRPCPP = @HAVE_ULXMLRPCPP@
STANDALONE_CLEARINGHOUSE = @STANDALONE_CLEARINGHOUSE@
NODE_USAGE_SUPPORT = @NODE_USAGE_SUPPORT@
MERGE_BUILD = @MERGE_BUILD@
MERGE_BUILD_SANDBOX = @MERGE_BUILD_SANDBOX@
EXP_VIS_SUPPORT = @EXP_VIS_SUPPORT@
TESTBED_LIBSRCDIR = ${TESTBED_SRCDIR}/clientside/lib
TESTBED_LIBOBJDIR = ${OBJDIR}/clientside/lib
TESTBED_IMAGEZIPSRCDIR = ${TESTBED_SRCDIR}/clientside/os/imagezip
Emulab network testbed source release
Version 5.0
September 1, 2008
University of Utah, Flux Research Group
Welcome to Emulab!
This is the first "official" release of the full current source code for the
software that runs the Emulab network testbed at the University of Utah,
as well as over 20 testbeds at other sites:
This is the "official" source code for the software that runs the Emulab
network testbed at the University of Utah, as well as dozens of testbeds at
other sites around the world.
http://www.emulab.net/
http://www.emulab.net/
This is a snapshot of a rapidly-evolving system. It contains all Emulab
This is a snapshot of a rapidly evolving system. It contains all Emulab
source required to build a running testbed, but interaction with Emulab
admins at Utah and elsewhere will likely be required to get things up
and running.
Emulab is being actively developed, so there may be features in deployed
Emulabs (in particular, Utah's) that are not included in this release.
In the future it is our intention to make new snapshots frequently.
Emulab is also a research project, and is rapidly evolving to satisfy the
needs of both our research needs and external researchers. For that reason,
you might find bugs! We hope you will tell us about them (nicely) and maybe
even help us to fix them. More on this below.
HOW TO SETUP AN EMULAB
The Emulab installation documentation is located on the Utah Emulab Wiki:
http://users.emulab.net/trac/emulab/wiki/InstallRoot
under "Installation Documentation".
https://users.emulab.net/trac/emulab/wiki/InstallRoot
HOW TO UPDATE AN EMULAB
Updating your existing Emulab is a bit harder than a fresh install,
as different sites are running different combinations of FreeBSD,
FreeBSD ports, and Emulab software. A process that we hope will work
for most sites is located on the Utah Emulab Wiki:
http://users.emulab.net/trac/emulab/wiki/InstallRoot
under "Upgrade Documentation".
Updating your existing Emulab is a bit harder than a fresh install, but is
mostly automated. A process that we hope will work for most sites is
located on the Utah Emulab Wiki:
http://users.emulab.net/trac/emulab/wiki/InstallRoot
under "Upgrade Documentation."
TRACKING THE EMULAB SOURCE CODE
We encourage you to track the Emulab source code in real time and stay
current with our stable versions. More info on how to access the
Emulab source code repository is here:
http://users.emulab.net/trac/emulab/wiki/GitRepository
MAILING LISTS
If you are bringing up an Emulab, be sure to join the mailing list:
testbed-admins@flux.utah.edu
http://www.flux.utah.edu/mailman/listinfo/testbed-admins
emulab-admins@googlegroups.com
http://groups.google.com/group/emulab-admins
which has open archives.
Users of your Emulab should join the Emulab users group, which is intended
for all users of Emulabs anywhere, to help each other:
emulab-users@googlegroups.com
http://groups.google.com/group/emulab-users
HELP/CONTACT INFORMATION
For help and to report bugs and problems, mail
testbed-admins@flux.utah.edu (preferable)
or
testbed-ops@flux.utah.edu (if you insist on privacy)
For help and to report bugs and problems, mail to
emulab-admins@googlegroups.com
Don't be shy! In most cases, you will have the same questions other people
have. Search the archives, too! There is lots of good information there.
Don't be shy! We may be able to get on the phone with you, too,
for "big picture" issues and problems.
COPYRIGHT, LICENSE, AND DISTRIBUTION
Emulab is copyrighted by the Flux Research Group and the University of Utah.
LICENSE
See the file AGPL-COPYING for licensing conditions. In summary, the
Emulab software is distributed under a free and open source license, the
GNU Affero General Public License version 3 (AGPLv3). The AGPLv3
consists of the GNU General Public License version 3 (GPLv3) with a
single short added Section 13, which requires that the source be freely
This release of the Emulab software is distributed under the terms of the GNU
Affero General Public License, version 3 (AGPLv3). The AGPLv3 is a popular
open source license; see the file AGPL-COPYING for licensing conditions. The
AGPLv3 consists of the GNU General Public License version 3 (GPLv3) with a
single short addition (Section 13), which requires that the source be freely
available to all users who interact with the software through a network.
The Emulab source tree contains various third-party, open-source packages that
are used by Emulab. These third-party packages are copyrighted and licensed as
described in their source files.
The development of Emulab has been supported by numerous organizations
including NSF, DARPA, Intel, HP, Microsoft, Novell, Nortel, and the University
of Utah. We thank all of these organizations for making Emulab possible.
The following statement is required by DARPA and pertains to DARPA's support
for portions of the Emulab software:
DoD Distribution Statement A: Approved for public release; distribution is
unlimited.
DOCUMENTATION
We are in the process of moving all our documentation to the Utah Emulab
wiki at
http://users.emulab.net/trac/emulab/wiki/ .
Soon, but not yet, that should be considered the primary source of
information.
All of the Emulab documentation is available from the Utah Emulab site:
http://users.emulab.net/trac/emulab/wiki
Within this source tree,
- doc/* contains documentation for developers.
- www/*.html and www/{doc,tutorial}/*.html contain end-user documentation,
all linked from www/doc.php3.
We encourage people to help us improve our documentation. If you want to
make changes, please apply for an account at Utah; anyone with an account
at the Utah Emulab is allowed to edit the Wiki pages.
Other good places to start would include:
- The search box at www.emulab.net for the absolutely latest FAQs and info
- The user tutorial (www/tutorial/tutorial.html)
- The user FAQ (www/faq.html)
- The user authorization document (www/auth.html)
- Software architecture preliminary diagram (doc/arch-diagram.ps)
- Notes on the source tree and architecture (doc/arch.txt)
- Overview of some major systems (doc/overview.txt)
- The doc/papers directory, which contains a few of the papers we've
published about Emulab
- Diagrams and brief explanations of the state machines used in the
system (www/doc/states.html and www/doc/*.gif)
- Mail we have exchanged with others about hardware recommendations
(doc/hardware-mail.mbox)
- The search box at www.emulab.net
- The Emulab Wiki (http://users.emulab.net/trac/emulab/wiki)
- Getting Started document (http://users.emulab.net/trac/emulab/wiki/Auth)
- The user tutorial (http://users.emulab.net/trac/emulab/wiki/Tutorial)
- The user FAQ (http://users.emulab.net/trac/emulab/wiki/FAQ)
- Papers and talks about Emulab (http://www.emulab.net/pubs.php3)
- Papers using Emulab (http://www.emulab.net/expubs.php)
QUICK TOUR
- The Database maintains most testbed state.
* LibDB (db/libdb.pm.in) and the assorted modules (db/*.pm.in) are the
main DB interface for testbed software.
- The database maintains most testbed state.
* Assorted modules (db/*.pm.in) are the main DB interface for testbed
software.
* sql/database-create.sql contains the DB schema.
- The Web Interface (www/*) is the primary means of managing and
interfacing with the system. There is also an experimental
- The Web interface (www/*) is the primary means of managing and
interfacing with the system. There is also an experimental
standalone GUI that uses this interface.
- The tbsetup and backend directories contain the bulk of the server-side
experiment setup and management code.
* startexp (tbsetup/startexp.in) is the backend for experiment creation;
Important scripts it calls include tbprerun (tbsetup/tbprerun.in)
* startexp (tbsetup/startexp.in) is the back end for experiment creation.
Important scripts it calls include tbprerun (tbsetup/tbprerun.in)
and tbswap (tbsetup/tbswap.in).
* ns2ir (tbsetup/ns2ir/*) converts NS files to DB state (via TCL and XML).
* snmpit (tbsetup/snmpit.in) configures VLANs on switch hardware.
- assign (assign/*) maps experiments to available hardware.
- The frisbee subsystem (os/frisbee.redux, os/imagezip) is used for creation
and rapid deployment of disk images.
- The frisbee subsystem (os/frisbee.redux, os/imagezip) is used for the
creation and rapid deployment of disk images.
- The client-driven node configuration is handled by scripts on the client
which communicate with the server via a custom configuration protocol.
......@@ -123,12 +139,12 @@ SOURCE TREE ORGANIZATION
account - Account creation and management
apache - Apache HTTPD configuration
assign - Resource allocation software
backend - Server-side of the Emulab XML RPC interface
backend - Server-side of the Emulab XML-RPC interface
bugdb - Optional per-project bug database
capture - Node serial line server software
cdrom - Software related to CD-booting local and remote machines
collab - Optional per-project "collaboration" tools: CVS, jabber, mailman
db - Variety of interfaces to testbed state
db - Variety of interfaces to testbed state
delay - RHL9 patches for supporting "end-node" traffic shaping
dhcpd - DHCPD configuration
doc - Documentation (mainly internal)
......@@ -144,7 +160,7 @@ mote - Initial testbed support for Berkeley/Crossbow motes
named - BIND configuration files
os - Client-side software (disk loading, route calculation, etc.)
patches - Patches needed to compile standard software packages
pelab - Preliminary support for "Flexlab", an Emulab/PlanetLab hybrid
pelab - Preliminary support for "Flexlab," an Emulab/PlanetLab hybrid
(see http://www.cs.utah.edu/flux/flexlab/)
protogeni - Evolving software for a prototype GENI system based on Emulab
(see http://www.protogeni.net/)
......@@ -163,31 +179,9 @@ tmcd - Testbed master control daemon and client (for node configuration)
tools - Miscellaneous infrastructure tools
utils - Testbed configuration and maintenance tools
vis - Experiment visualization
wiki - Support for per-project WIKIs
wiki - Support for per-project Wikis
www - Web Interface / User Documentation
xmlrpc - Programatic XML-RPC interface to testbed
UPGRADING FROM the 4.9.0 RELEASE
There are a surprising number of differences given that we have only
advanced 0.1 in version! In a nutshell:
* Updated FreeBSD packages from FreeBSD 6.1-era to 6.3-era
* Much more of the documentation has moved into the Wiki
* Changes to the (unused) "protogeni" code
* Improvements to the installation scripts
* Integration of code/fixes from Keith Sklower and DETER (Thanks!)
* Assorted fixes
If you did install the 4.9 release on FreeBSD 6.3, and want to upgrade
to 5.0 (you should), it should be straightforward. You will need to apply
the sql/database-migrate.txt changes 4.157 to 4.160 (which are all trivial)
and rebuild and reinstall your Emulab software.
It would be good to also update your ports. In theory, this is all handled
by a magic script we provide. Refer to the "Update ports" section of
http://users.emulab.net/trac/emulab/wiki/appendix/upgrade-410-63.html
Good luck!
Jay Lepreau, lepreau@cs.utah.edu, and the Utah testbed crew.
September 1, 2008
The Emulab Team
Version: $Format:%H %ci$
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2007 University of Utah and the Flux Group.
# All rights reserved.
#
# {{{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/>.
#
# }}}
#
use English;
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2009 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2000-2024 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@
......@@ -13,16 +30,22 @@ UNIFIED = @UNIFIED_BOSS_AND_OPS@
include $(OBJDIR)/Makeconf
SBIN_STUFF = tbacct addsfskey addpubkey mkusercert quotamail genpubkeys \
newuser newproj mksyscert
newuser newproj mksyscert spewcert dumpuser dumpproject \
manageremote regencerts
LIBEXEC_STUFF = webtbacct webaddsfskey webaddpubkey webmkusercert \
webnewuser webnewproj
CTRLSBIN_STUFF = adduserhook
webnewuser webnewproj webspewcert webmanageremote
CTRLSBIN_STUFF = adduserhook accountsetup
# These scripts installed setuid, with sudo.
SETUID_BIN_SCRIPTS =
SETUID_SBIN_SCRIPTS = tbacct addpubkey mkusercert mksyscert
SETUID_LIBX_SCRIPTS =
ifeq ($(PROTOGENI_SUPPORT),1)
SBIN_STUFF += manageremote
SETUID_SBIN_SCRIPTS += manageremote
endif
#
# Targets
#
......@@ -51,7 +74,8 @@ boss-install: all script-install
@echo "Don't forget to do a post-install as root"
script-install: $(addprefix $(INSTALL_SBINDIR)/, $(SBIN_STUFF)) \
$(addprefix $(INSTALL_LIBEXECDIR)/, $(LIBEXEC_STUFF))
$(addprefix $(INSTALL_LIBEXECDIR)/, $(LIBEXEC_STUFF)) \
$(addprefix $(INSTALL_DIR)/opsdir/sbin/, $(CTRLSBIN_STUFF))
post-install:
chmod 775 $(INSTALL_BINDIR)
......
This diff is collapsed.
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2008 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2000-2020 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/>.
#
# }}}
#
use English;
use Getopt::Std;
use XML::Simple;
use File::Temp qw(tempfile :POSIX );
#
# Parse ssh public keys and enter into the DB. The default format is
......@@ -31,7 +49,7 @@ sub usage()
print " -r Force a regenerate of initial key for user\n";
exit(-1);
}
my $optlist = "dkniwfu:rX:";
my $optlist = "dkniwfu:rX:sRNC:S:Ia";
my $iskey = 0;
my $verify = 0;
my $initmode = 0;
......@@ -39,6 +57,11 @@ my $force = 0;
my $genmode = 0;
my $nobody = 0;
my $noemail = 0;
my $remove = 0;
my $nodelete = 0;
my $internal = 0;
my $isaptkey = 0;
my $Comment;
my $xmlfile;
#
......@@ -48,7 +71,11 @@ my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $TBAUDIT = "@TBAUDITEMAIL@";
my $OURDOMAIN = "@OURDOMAIN@";
my $CONTROL = "@USERNODE@";
my $KEYGEN = "/usr/bin/ssh-keygen";
my $ACCOUNTPROXY= "$TB/sbin/accountsetup";
my $SSH = "$TB/bin/sshtb";
my $SAVEUID = $UID;
my $USERUID;
# Locals
......@@ -63,6 +90,7 @@ my $user_name;
my $user_email;
my $user_dbid;
my $user_uid;
my $user_gid;
my $debug = 0;
#
......@@ -72,6 +100,10 @@ use lib "@prefix@/lib";
use libaudit;
use libdb;
use libtestbed;
use User;
if (@PROTOGENI_SUPPORT@) {
require APT_Utility;
}
#
# Function prototypes
......@@ -134,6 +166,9 @@ if (! getopts($optlist, \%options)) {
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"a"})) {
$isaptkey = 1;
}
if (defined($options{"k"})) {
$iskey = 1;
}
......@@ -146,15 +181,30 @@ if (defined($options{"n"})) {
if (defined($options{"i"})) {
$initmode = 1;
}
if (defined($options{"N"})) {
$nodelete = 1;
}
if (defined($options{"I"})) {
$internal = 1;
}
if (defined($options{"r"})) {
$force = 1;
}
if (defined($options{"R"})) {
$remove = 1;
}
if (defined($options{"s"})) {
$noemail = 1;
}
if (defined($options{"w"})) {
$genmode = 1;
}
if (defined($options{"u"})) {
$user = $options{"u"};
}
if (defined($options{"C"})) {
$Comment = $options{"C"};
}
if (defined($options{"X"})) {
$xmlfile = $options{"X"};
......@@ -215,6 +265,18 @@ if (defined($user)) {
$user_dbid = $target_user->dbid();
$user_uid = $target_user->uid();
$USERUID = $target_user->unix_uid();
my $firstproject;
if ($target_user->FirstApprovedProject(\$firstproject) < 0) {
fatal("Could not determine first approved project");
}
if (defined($firstproject)) {
$user_gid = $firstproject->unix_gid();
}
else {
$user_gid = "guest";
}
}
#
......@@ -240,18 +302,16 @@ else {
}
#
# Initmode or genmode, do it and exit. Eventually get rid of the switch
# to the target user.
# Initmode or genmode, do it and exit.
#
if ($initmode) {
# Drop root privs, switch to target user.
$EUID = $UID = $USERUID;
exit InitUser();
}
if ($genmode) {
# Drop root privs, switch to target user.
$EUID = $UID = $USERUID;
exit GenerateKeyFile();
if ($initmode || $genmode) {
if ($initmode) {
exit(InitUser());
}
if ($genmode) {
exit(GenerateKeyFile());
}
exit(1);
}
# Else, key parse mode ...
......@@ -274,29 +334,40 @@ else {
if (! -e $keyfile) {
fatal("No such file: $keyfile\n");
}
$keyline = `head -1 $keyfile`;
open(KEY, "$keyfile")
or fatal("Could not open $keyfile to read");
#
# Ick, look at first line to see if it looks like an openssh key,
# and if so we want to remove the embedded newlines.
#
$keyline = <KEY>;
my $chompit = 0;
if ($keyline =~ /^ssh/ || $keyline =~ /^\d+\s+\d+/) {
$chompit = 1;
}
while (<KEY>) {
chomp($_) if ($chompit);
$keyline .= $_;
}
close(KEY);
}
#
# Check user
#
if (!$verify) {
# If its the user himself, then we can generate a new authkeys file.
if (!$target_user->SameUser($this_user) && !TBAdmin()) {
# If its the user himself, then we can generate a new authkeys file.
# Assume nodelete option comes from internal script, so do not worry.
if (!$target_user->SameUser($this_user) && !$this_user->IsAdmin() &&
!$nodelete) {
fatal("You are not allowed to set pubkeys for $target_user\n");
}
if (-d "$HOMEDIR/$user_uid/.ssh") {
if ($target_user->SameUser($this_user) && $this_user->active()) {
# Drop root privs, switch to target user.
$EUID = $UID = $USERUID;
$genmode = 1;
}
#
# This script is audited when not in verify mode. Since all keys are first
# checked with verify mode, this should not cause any extra email from bad
# keys.
#
AuditStart(0);
}
#
......@@ -339,7 +410,7 @@ sub ParseKey($) {
return 0;
}
if ($keyline =~ /^(\d*\s\d*\s[0-9a-zA-Z]*) ([-\w\@\.\ ]*)\s*$/) {
if ($keyline =~ /^(\d*\s\d*\s[0-9a-zA-Z]*) ([-\\\w\@\.:\ ]*)\s*$/) {
# Protocol 1
$type = "ssh-rsa1";
$key = $1;
......@@ -351,21 +422,20 @@ sub ParseKey($) {
$key = $1;
}
elsif ($keyline =~
/^(ssh-rsa|ssh-dss) ([-\w\.\@\+\/\=]*) ([-\w\@\.\ ]*)$/) {
/^(ssh-rsa|ssh-ed25519) ([-\w\.\@\+\/\=]*) ([-\\\w\@\.:\ ]*)$/) {
# Protocol 2
$type = $1;
$key = "$1 $2";
$comment = $3;
}
elsif ($keyline =~ /^(ssh-rsa|ssh-dss) ([-\w\.\@\+\/\=]*)$/) {
elsif ($keyline =~ /^(ssh-rsa|ssh-ed25519) ([-\w\.\@\+\/\=:]*)$/) {
# Protocol 2 but no comment field
$type = $1;
$key = "$1 $2";
}
if (!defined($key)) {
print "Key cannot be parsed!\n";
print "Key: $keyline\n";
print STDERR "Key cannot be parsed, we accept rsa and ed25519 only!\n";
return 0;
}
......@@ -379,19 +449,34 @@ sub ParseKey($) {
# Make up a comment field for the DB.
#
if (!defined($comment)) {
$comment = "$type-${user_email}";
$comment = (defined($Comment) ? $Comment : "$type-${user_email}");
}
$key = "$key $comment";
my $safe_key = DBQuoteSpecial($key);
my $safe_comment = DBQuoteSpecial($comment);
DBQueryFatal("replace into user_pubkeys ".
"values ('$user_uid', '$user_dbid', ".
" 0, '$key', now(), '$comment')");
if ($remove) {
DBQueryFatal("delete from user_pubkeys ".
"where uid_idx='$user_dbid' and comment=$safe_comment");
}
# Only one APT key allowed
if ($isaptkey) {
DBQueryFatal("delete from user_pubkeys ".
"where uid_idx='$user_dbid' and isaptkey=1");
}
DBQueryFatal("replace into user_pubkeys set ".
" uid='$user_uid', uid_idx='$user_dbid', ".
" internal='$internal', nodelete='$nodelete', ".
" isaptkey='$isaptkey',idx=NULL, stamp=now(), ".
" pubkey=$safe_key, comment=$safe_comment");
#
# Mark user record as modified so nodes are updated.
#
TBNodeUpdateAccountsByUID($user_uid);
if (@PROTOGENI_SUPPORT@) {
APT_Utility::UpdateInstancesByUser($target_user);
}
my $chunked = "";
while (length($key)) {
......@@ -414,7 +499,7 @@ sub ParseKey($) {
"SSH Public Key for '$user_uid' added:\n".
"\n".
"$chunked\n",
"$TBOPS");
"$TBOPS", "Bcc: $TBAUDIT");
}
return 1;
}
......@@ -426,96 +511,47 @@ sub ParseKey($) {
#
sub InitUser()
{
my $sshdir = "$HOMEDIR/$user_uid/.ssh";
#
# Set up the ssh key, but only if not done so already.
#
if (! -e "$sshdir") {
mkdir("$sshdir", 0700) or
fatal("Could not mkdir $sshdir: $!");
}
if (! -e "$sshdir/identity" || $force) {
print "Creating ssh protocol 1 key for $user.\n";
#
# Want to delete existing key from DB.
#
if (-e "$sshdir/identity") {
my $ident = `cat $sshdir/identity.pub`;
if ($ident =~ /(\d*\s\d*\s[0-9a-zA-Z]*)\s([-\w\@\.]*)/) {
DBQueryFatal("delete from user_pubkeys ".
"where uid_idx='$user_dbid' and pubkey='$1 $2'");
}
unlink("$sshdir/identity");
}
# Hmm, need to use -C option so comment field makes sense.
if (system("$KEYGEN -t rsa1 -P '' ".
"-C '${user}" . "\@" . ${OURDOMAIN} . "' ".
"-f $sshdir/identity")) {
fatal("Failure in ssh-keygen!");
}
#
# Grab a copy for the DB.
#
my $ident = `cat $sshdir/identity.pub`;
if ($ident =~ /(\d*\s\d*\s[0-9a-zA-Z]*)\s([-\w\@\.]*)/) {
DBQueryFatal("replace into user_pubkeys ".
"values ('$user_uid', '$user_dbid', ".
" 0, '$1 $2', now(), '$2')");
}
else {
fatal("Bad protocol 1 public key: $ident\n");
}
}
#
# Moving to V2 keys ...
# Want to delete existing keys from DB, but not the sslcert key.
#
if (! -e "$sshdir/id_rsa" || $force) {
print "Creating ssh protocol 2 key for $user.\n";
#
# Want to delete existing key from DB.
#
if (-e "$sshdir/id_rsa") {
my $ident = `cat $sshdir/id_rsa.pub`;
if ($ident =~
/^(ssh-rsa [-\w\.\@\+\/\=]*) ([-\w\@\.\ ]*)$/) {
DBQueryFatal("delete from user_pubkeys ".
"where uid_idx='$user_dbid' and pubkey='$1 $2'");
}
unlink("$sshdir/id_rsa");
}
# Hmm, need to use -C option so comment field makes sense.
DBQueryFatal("delete from user_pubkeys ".
"where uid_idx='$user_dbid' and ".
" (internal=1 or comment like '%\@${OURDOMAIN}' or ".
" comment like '%\@boss.${OURDOMAIN}') and ".
" isaptkey=0 and comment not like 'sslcert:%'");
# Redirect pub key to file, redirect STDERR to STDIN for display.
my $outfile = tmpnam();
my $command = "$ACCOUNTPROXY createsshkey $user_uid $user_gid ";
$UID = 0;
open ERR, "$SSH -host $CONTROL '$command rsa' 2>&1 > $outfile |";
$UID = $SAVEUID;
$errs = "";
while (<ERR>) {
$errs .= $_;
}
close(ERR);
print STDERR $errs;
if ($?) {
unlink($outfile);
fatal("Could not create rsa key");
}
$pubkey = `cat $outfile`;
chomp($pubkey);
$safe_pubkey = DBQuoteSpecial($pubkey);
$comment = "rsa\@${OURDOMAIN}";
if (system("$KEYGEN -t rsa -P '' ".
"-C '${user}" . "\@" . ${OURDOMAIN} . "' ".
"-f $sshdir/id_rsa")) {
fatal("Failure in ssh-keygen!");
}
#
# Grab a copy for the DB.
#
my $ident = `cat $sshdir/id_rsa.pub`;
if ($ident =~
/^(ssh-rsa [-\w\.\@\+\/\=]*) ([-\w\@\.\ ]*)$/) {
DBQueryFatal("replace into user_pubkeys ".
"values ('$user_uid', '$user_dbid', ".
" 0, '$1 $2', now(), '$2')");
}
else {
fatal("Bad protocol 2 public key: $ident\n");
}
}
if (! DBQueryWarn("replace into user_pubkeys set ".
" uid='$user_uid', uid_idx='$user_dbid', ".
" internal='1', nodelete='1', idx=NULL, stamp=now(), ".
" pubkey=$safe_pubkey, comment='$comment'")) {
unlink($outfile);
fatal("Could not add rsa key to database");
}
unlink($outfile);
return GenerateKeyFile();
}
......@@ -526,15 +562,9 @@ sub InitUser()
sub GenerateKeyFile()
{
my @pkeys = ();
my $outfile = tmpnam();
my $sshdir = "$HOMEDIR/$user_uid/.ssh";
my $keyfile = "$sshdir/authorized_keys";
if (! -e $sshdir) {
if (! mkdir($sshdir, 0700)) {
warn("*** WARNING: Could not mkdir $sshdir: $!\n");
return -1;
}
}
my $query_result =
DBQueryFatal("select pubkey from user_pubkeys ".
"where uid_idx='$user_dbid'");
......@@ -543,15 +573,14 @@ sub GenerateKeyFile()
push(@pkeys, $key);
}
print "Generating $keyfile ...\n";
if (!open(AUTHKEYS, "> ${keyfile}.new")) {
warn("*** WARNING: Could not open ${keyfile}.new: $!\n");
print "Generating authorized_keys ...\n";
if (!open(AUTHKEYS, "> $outfile")) {
warn("*** WARNING: Could not open $outfile: $!\n");
return -1;
}
print AUTHKEYS "#\n";
print AUTHKEYS "# DO NOT EDIT! This file auto generated by ".
"Emulab.Net account software.\n";
"Emulab account software.\n";
print AUTHKEYS "#\n";
print AUTHKEYS "# Please use the web interface to edit your ".
"public key list.\n";
......@@ -562,28 +591,17 @@ sub GenerateKeyFile()
}
close(AUTHKEYS);
if (!chmod(0600, "${keyfile}.new")) {
warn("*** WARNING: Could not chmod ${keyfile}.new: $!\n");
return -1;
}
if (-e "${keyfile}") {
if (system("cp -p -f ${keyfile} ${keyfile}.old")) {
warn("*** Could not save off ${keyfile}: $!\n");
return -1;
}
if (!chmod(0600, "${keyfile}.old")) {
warn("*** Could not chmod ${keyfile}.old: $!\n");
}
}
if (system("mv -f ${keyfile}.new ${keyfile}")) {
warn("*** Could not mv ${keyfile} to ${keyfile}.new: $!\n");
}
elsif (-e "$sshdir/authorized_keys2") {
#
# Save to remove deprecated authorized_keys2 file at this point.
#
unlink("$sshdir/authorized_keys2");
$EUID = $UID = 0;
system("$SSH -host $CONTROL ".
"'$ACCOUNTPROXY dropfile $user_uid $user_gid 0600 $sshdir ".
"authorized_keys' < $outfile");
$EUID = $UID = $SAVEUID;
if ($?) {
unlink($outfile);
fatal("Could not copy authorized_keys file to $CONTROL");
}
unlink($outfile);
return 0;
}
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2004, 2006 University of Utah and the Flux Group.
# All rights reserved.
#
# {{{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/>.
#
# }}}
#
use English;
use Getopt::Std;
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2008 University of Utah and the Flux Group.
# All rights reserved.
#
# {{{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/>.
#
# }}}
#
use strict;
use English;
......
#!/usr/bin/perl -w
#
# Copyright (c) 2010-2011 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/>.
#
# }}}
#
use English;
use strict;
use Getopt::Std;
use CGI;
use Data::Dumper;
#
# Dump a project in XML format suitable for reading into newproj script.
#
sub usage()
{
print("Usage: dumpproject [-d] <pid>\n");
exit(-1);
}
my $optlist = "d";
my $debug = 0;
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
#
# Untaint the path
#
$ENV{'PATH'} = "$TB/bin:$TB/sbin:/bin:/usr/bin:/usr/bin:/usr/sbin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Turn off line buffering on output
#
$| = 1;
#
# Load the Testbed support stuff.
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
use User;
use Project;
# Protos
sub fatal($);
sub DumpProject($);
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
my %options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = 1;
}
if (@ARGV != 1) {
usage();
}
my $pid = $ARGV[0];
# Map invoking user to object.
my $this_user = User->ThisUser();
if (! defined($this_user)) {
fatal("You ($UID) do not exist!");
}
#
# Figure out who called us. Must have admin status to do this.
#
if (!$this_user->IsAdmin()) {
fatal("You must be a TB administrator to run this script!");
}
# Map target user to object.
my $project = Project->Lookup($pid);
if (! defined($project)) {
fatal("$pid does not exist!");
}
DumpProject($project);
exit(0);
#
# Dump the project in XML.
#
sub DumpProject($)
{
my ($project) = @_;
# Array of string values to print.
my %xmlnames = (
"pid" => {"tag" => "name",
"optional" => 0 },
"head_uid" => {"tag" => "leader",
"optional" => 0 },
"description" => {"tag" => "short description",
"optional" => 0 },
"URL" => {"tag" => "URL",
"optional" => 0 },
"funders" => {"tag" => "funders",
"optional" => 0 },
"why" => {"tag" => "long description",
"optional" => 0 },
"public" => {"tag" => "public",
"optional" => 0 },
"num_pcs" => {"tag" => "num_pcs",
"optional" => 0 },
"linked_to_us" => {"tag" => "linkedtous",
"optional" => 0 },
);
print "<project>\n";
foreach my $key (keys(%xmlnames)) {
my $ref = $xmlnames{$key};
my $tag = $ref->{'tag'};
my $optional = $ref->{'optional'};
my $val = $project->$key();
next
if (!defined($val) && $optional);
$val = "None"
if (!defined($val) &&
($key eq "funders" || $key eq "why"));
print " <attribute name=\"$tag\">";
print "<value>" . CGI::escapeHTML($val) . "</value>";
print "</attribute>\n";
}
print "</project>\n";
}
sub fatal($)
{
my ($mesg) = @_;
print STDERR "*** $0:\n".
" $mesg\n";
exit(-1);
}
#!/usr/bin/perl -w
#
# Copyright (c) 2010-2020 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/>.
#
# }}}
#
use English;
use strict;
use Getopt::Std;
use CGI;
use Data::Dumper;
#
# Dump a user in XML format suitable for reading into newuser script.
#
sub usage()
{
print("Usage: dumpuser [-d] [-p] <uid>\n");
exit(-1);
}
my $optlist = "dp";
my $debug = 0;
my $nopswd = 0;
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $PGENISUPPORT= @PROTOGENI_SUPPORT@;
my $OURDOMAIN = "@OURDOMAIN@";
#
# Untaint the path
#
$ENV{'PATH'} = "$TB/bin:$TB/sbin:/bin:/usr/bin:/usr/bin:/usr/sbin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Turn off line buffering on output
#
$| = 1;
#
# Load the Testbed support stuff.
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
use User;
use Project;
if ($PGENISUPPORT) {
require GeniHRN;
}
# Protos
sub fatal($);
sub DumpUser($);
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
my %options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"p"})) {
$nopswd = 1;
}
if (@ARGV != 1) {
usage();
}
my $user = $ARGV[0];
# Map invoking user to object.
my $this_user = User->ThisUser();
if (! defined($this_user)) {
fatal("You ($UID) do not exist!");
}
# Map target user to object.
my $target_user = User->Lookup($user);
if (! defined($target_user)) {
fatal("$user does not exist!");
}
DumpUser($target_user);
exit(0);
#
# Dump the user in XML.
#
sub DumpUser($)
{
my ($user) = @_;
my @keys = ();
# Array of string values to print.
my %xmlnames = (
"name" => {"tag" => "name",
"optional" => 0 },
"email" => {"tag" => "email",
"optional" => 0 },
"pswd" => {"tag" => "passhash",
"optional" => 0 },
"uid" => {"tag" => "uid",
"optional" => 0 },
"URL" => {"tag" => "URL",
"optional" => 1 },
"addr" => {"tag" => "address",
"optional" => 1 },
"addr2" => {"tag" => "address2",
"optional" => 1 },
"city" => {"tag" => "city",
"optional" => 0 },
"state" => {"tag" => "state",
"optional" => 0 },
"zip" => {"tag" => "zip",
"optional" => 1 },
"country" => {"tag" => "country",
"optional" => 0 },
"phone" => {"tag" => "phone",
"optional" => 1 },
"title" => {"tag" => "title",
"optional" => 1 },
"affil" => {"tag" => "affiliation",
"optional" => 0 },
"shell" => {"tag" => "shell",
"optional" => 1 },
"wikiname" => {"tag" => "wikiname",
"optional" => 1 },
"affil_abbrev" => {"tag" => "affiliation_abbreviation",
"optional" => 0 },
);
$user->GetSSHKeys(\@keys) == 0
or fatal("Could not net ssh keys");
print "<userinfo>\n";
foreach my $key (keys(%xmlnames)) {
my $ref = $xmlnames{$key};
my $tag = $ref->{'tag'};
my $optional = $ref->{'optional'};
my $val = $user->$key();
next
if ($optional && (!defined($val) || $val eq ""));
$val = "None"
if (!defined($val) && $key eq "affil_abbrev");
next
if ($nopswd && $key eq "pswd");
print " <attribute name=\"$tag\">";
print "<value>" . CGI::escapeHTML($val) . "</value>";
print "</attribute>\n";
}
# Pubkeys are special.
if (@keys) {
foreach my $key (@keys) {
next
if ($key =~ /^ssh-dss/);
print "<pubkeys>$key</pubkeys>\n";
}
}
print "</userinfo>\n";
}
sub fatal($)
{
my ($mesg) = @_;
print STDERR "*** $0:\n".
" $mesg\n";
exit(-1);
}
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
# All rights reserved.
#
# {{{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/>.
#
# }}}
#
use English;
use Getopt::Std;
......
#!/usr/bin/perl -w
#
# Copyright (c) 2005-2022 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/>.
#
# }}}
#
use English;
use strict;
use Getopt::Std;
use Data::Dumper;
use File::Temp qw(tempfile);
use JSON;
#
# Ask https://ipinfo.io/ for IP info
#
# select cc.country,sum(t.count) as count from
# (select country,count(distinct(uid)) as count from login_history
# where IP is not null and location is not null and portal='cloudlab'
# group by country,uid) as t
# left join ccodes.ccodes as cc on cc.code=t.country
# group by cc.country order by count desc;
#
#select region,sum(t.count) as count from
# (select region,count(distinct(uid)) as count from login_history
# where IP is not null and location is not null and country='US' and
# portal='cloudlab'
# group by region,uid) as t
#group by region order by count desc;
#
#
sub usage()
{
print "Usage: getipinfo [-n]\n";
print " getipinfo [-n] -p portal\n";
exit(1);
}
my $optlist = "ndp:";
my $impotent = 0;
my $debug = 0;
my $limit = 200;
#
# Configure variables
#
my $TB = "@prefix@";
my $token = "850749cc3b77dc";
my $URL = "http://ipinfo.io/batch?token=${token}";
my $CURL = "/usr/local/bin/curl";
# Load the Testbed support stuff.
use lib "@prefix@/lib";
use emdb;
use User;
use emutil;
# Protos
sub fatal($);
sub WriteResults($);
#
# Turn off line buffering on output
#
$| = 1;
my %options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"n"})) {
$impotent++;
}
if (defined($options{"d"})) {
$debug++;
}
if (defined($options{"p"})) {
my $portal = $options{"p"};
if ($portal ne "cloudlab" && $portal ne "powder") {
fatal("Only cloudlab or powder portal please");
}
exit(WriteResults($portal));
}
#
# Find unmatched IPs in the login_history table and batch them up
# for the request.
#
my $count = 0;
while ($limit) {
$limit--;
my $query_result =
DBQueryFatal("select distinct IP from login_history ".
"where location is null and IP is not null ".
"limit 100");
last
if ($query_result->numrows == 0);
my %IPs = ();
while (my ($IP) = $query_result->fetchrow_array()) {
$IPs{$IP} = $IP;
}
if (keys(%IPs)) {
# Create a temporary files for curl
my ($fpIn, $fnameIn) = tempfile("/tmp/iplistInXXXXX", UNLINK => 0);
if (!defined($fpIn)) {
fatal("Could not create temp file for IPs");
}
my ($fpOut, $fnameOut) = tempfile("/tmp/iplistOutXXXXX", UNLINK => 0);
if (!defined($fpOut)) {
fatal("Could not create temp file for IPs");
}
foreach my $IP (keys(%IPs)) {
print $fpIn "$IP\n";
}
my $command =
"$CURL -s -o $fnameOut -XPOST --data-binary \@${fnameIn} $URL";
if ($debug) {
print "$command\n";
}
system($command);
if ($?) {
fatal("curl failure: '$command'\n");
}
my $json = emutil::ReadFile($fnameOut);
if (!$json || $json eq "") {
fatal("No json received");
}
my $results = eval { decode_json($json) };
if ($@) {
fatal("Could not decode json data");
}
if ($debug) {
print Dumper($results);
}
foreach my $IP (keys(%IPs)) {
my $ref = $results->{$IP};
if (!defined($ref)) {
print STDERR "No data for $IP\n";
next;
}
my $loc = $ref->{'loc'};
my $country = $ref->{'country'};
my $region = $ref->{'region'};
if (!defined($loc)) {
print STDERR "No data for $IP\n";
DBQueryFatal("update login_history set ".
" location='' ".
"where IP='$IP'");
next;
}
$count++;
if ($impotent) {
print "Would set $IP: $loc,$country,$region\n";
next;
}
else {
print "$IP: $loc,$country,$region\n";
DBQueryFatal("update login_history set ".
" location=" . DBQuoteSpecial($loc) . ", ".
" country=" . DBQuoteSpecial($country) . ", ".
" region=" . DBQuoteSpecial($region) . " ".
"where IP='$IP'");
}
}
unlink($fnameIn);
unlink($fnameOut);
}
print "$count IPs completed\n";
last
if (!$count);
sleep(10);
}
exit(0);
#
# Write per portal results files. Queries take a while.
#
sub WriteResults($)
{
my ($portal) = @_;
print "These queries take time, get a cup of coffee.\n";
my $query_result =
DBQueryFatal("select cc.country,sum(t.count) as count from ".
" (select country,count(distinct(uid)) as count ".
" from login_history ".
" where IP is not null and location is not null and ".
" portal='$portal' ".
" group by country,uid) as t ".
"left join ccodes.ccodes as cc on cc.code=t.country ".
"group by cc.country order by count desc");
my $fname = "world-counts-${portal}.csv";
print "Writing $fname ... \n";
if (open(WORLD, ">$fname")) {
print WORLD "name,count\n";
while (my ($country,$count) = $query_result->fetchrow_array()) {
next
if (!defined($country));
$country = "USA"
if ($country eq "United States");
print WORLD "$country,$count\n";
}
close(WORLD);
}
else {
fatal("Could not open $fname for writing: $!\n");
}
$query_result =
DBQueryFatal("select region,sum(t.count) as count from ".
" (select region,count(distinct(uid)) as count ".
" from login_history ".
" where IP is not null and location is not null and ".
" country='US' and portal='$portal' ".
" group by region,uid) as t ".
"group by region order by count desc");
$fname = "us-counts-${portal}.csv";
print "Writing $fname ... \n";
if (open(STATES, ">$fname")) {
print STATES "name,count\n";
while (my ($region,$count) = $query_result->fetchrow_array()) {
next
if (!defined($region));
print STATES "$region,$count\n";
}
close(STATES);
}
else {
fatal("Could not open $fname for writing: $!\n");
}
exit(0);
}
sub fatal($) {
my($mesg) = $_[0];
die("*** $0:\n".
" $mesg\n");
}
#!/usr/bin/perl -w
#
# Copyright (c) 2010-2016, 2019 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
# GENI Public License
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and/or hardware specification (the "Work") to
# deal in the Work without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Work, and to permit persons to whom the Work
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Work.
#
# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS
# IN THE WORK.
#
# }}}
#
use strict;
use English;
use Getopt::Std;
use Data::Dumper;
use CGI;
#
#
#
sub usage()
{
print "Usage: manageremote version <remote>\n";
print " manageremote addpeer <remote> <urn> <url> [is_primary]\n";
print " manageremote adduser <remote> <uid>\n";
print " manageremote deluser <remote> <uid>\n";
print " manageremote moduser <remote> <uid>\n";
print " manageremote setgroups <remote> <uid>\n";
print " manageremote xlogin <remote> <uid>\n";
print " manageremote addproject <remote> <pid>\n";
print " manageremote addgroup <remote> <gid>\n";
exit(1);
}
my $optlist = "dnfp";
my $debug = 0;
my $force = 0;
my $impotent = 0;
my $locked = 0;
my $fromdaemon = 0;
#
# Function prototypes
#
sub Version();
sub AddUser(;$);
sub AddPeer();
sub DeleteUser();
sub ModifyUser();
sub SetGroups(;$);
sub CrossLogin();
sub AddProject();
sub AddGroup();
sub fatal($);
sub do_method($$;$);
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $TBLOGS = "@TBLOGSEMAIL@";
my $PGENISUPPORT = @PROTOGENI_SUPPORT@;
my $PEER_ENABLE = @PEER_ENABLE@;
my $PEER_PRIMARY = @PEER_ISPRIMARY@;
my $OURDOMAIN = "@OURDOMAIN@";
my $DUMPUSER = "$TB/sbin/dumpuser";
my $DUMPPROJ = "$TB/sbin/dumpproject";
my $SACERT = "$TB/etc/genisa.pem";
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin:/usr/site/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Turn off line buffering on output
#
$| = 1;
use lib '@prefix@/lib';
use emdb;
use libtestbed;
use User;
use Project;
use Group;
use emutil;
use GeniHRN;
use Genixmlrpc;
use GeniResponse;
use GeniCredential;
use GeniAuthority;
#
# Check args.
#
my %options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"f"})) {
$force = 1;
}
if (defined($options{"n"})) {
$impotent = 1;
}
if (defined($options{"p"})) {
$fromdaemon = 1;
}
usage()
if (@ARGV < 2 || @ARGV > 5);
my $cmd = shift(@ARGV);
my $peername = shift(@ARGV);
my $peerurn;
if (! $PEER_ENABLE) {
fatal("Peer mode is not enabled");
}
if (! ($PEER_PRIMARY || $cmd eq "addpeer")) {
fatal("You can only run addpeer on this boss");
}
#
# Map invoking user to object.
#
my $this_user = User->ThisUser();
if (! defined($this_user)) {
fatal("You ($UID) do not exist!");
}
#
# Mere users can call only one function.
#
if (!$this_user->IsAdmin() && $cmd ne "xlogin") {
fatal("You must be a TB administrator to run this script!");
}
#
# Load the SA cert to act as caller context.
#
my $certificate = GeniCertificate->LoadFromFile($SACERT);
if (!defined($certificate)) {
fatal("Could not load certificate from $SACERT\n");
}
my $context = Genixmlrpc->Context($certificate);
if (!defined($context)) {
fatal("Could not create context to talk to clearinghouse");
}
Genixmlrpc->SetContext($context);
my $me = GeniAuthority->Lookup($certificate->uuid());
if (!defined($me)) {
fatal("Could not find my own authority object");
}
my $credential = GeniCredential->GetSelfCredential($me);
if (!defined($credential)) {
fatal("Could not create self credential for $me");
}
my $authority;
#
# All operations other then AddPeer require that the peer be
# in the DB.
#
if ($cmd ne "addpeer") {
my $query_result =
DBQueryFatal("select name,urn from emulab_peers ".
"where name='$peername' or urn='$peername'");
fatal("Unknown peer")
if (!$query_result->numrows);
($peername,$peerurn) = $query_result->fetchrow_array();
$authority = GeniAuthority->CreateFromRegistry("sa", $peerurn);
if (!defined($authority)) {
fatal("Could not locate authority for $peername");
}
}
#
# All operations other then xlogin require locking to avoid a
# race with the peer_daemon.
#
if ($cmd ne "xlogin" && !$fromdaemon) {
while (TBScriptLock("portal_op", 0, 5) != TBSCRIPTLOCK_OKAY()) {
print "Could not get the lock; trying again ... ^C to stop trying.\n";
next;
}
$locked = 1;
}
#
# Now dispatch operation.
#
SWITCH: for ($cmd) {
/^version$/ && do {
Version();
last SWITCH;
};
/^adduser$/ && do {
AddUser();
last SWITCH;
};
/^addpeer$/ && do {
AddPeer();
last SWITCH;
};
/^deluser$/ && do {
DeleteUser();
last SWITCH;
};
/^moduser$/ && do {
ModifyUser();
last SWITCH;
};
/^setgroups$/ && do {
SetGroups();
last SWITCH;
};
/^xlogin$/ && do {
CrossLogin();
last SWITCH;
};
/^addproject$/ && do {
AddProject();
last SWITCH;
};
/^addgroup$/ && do {
AddGroup();
last SWITCH;
};
# Default
TBScriptUnlock()
if ($locked);
usage();
}
TBScriptUnlock()
if ($locked);
exit(0);
#
# Get the version.
#
sub Version()
{
my $response = do_method($authority, "GetVersion");
fatal("Could not get version from $authority")
if (! (defined($response) &&
$response->code() == GENIRESPONSE_SUCCESS));
my $version = $response->value();
print "Version: $version\n";
return 0;
}
#
# Add a peer to the list
#
sub AddPeer()
{
usage()
if (@ARGV < 2);
my $urn = shift(@ARGV);
my $url = shift(@ARGV);
my $primary = (@ARGV ? shift(@ARGV) : 0);
my $safe_url = DBQuoteSpecial($url);
$primary = ($primary ? 1 : 0);
fatal("Invalid URN")
if (!GeniHRN::IsValid($urn));
fatal("Invalid peer name")
if (! ($peername =~ /^[-\w]*$/));
my $authority = GeniAuthority->CreateFromRegistry("sa", $urn);
if (!defined($authority)) {
fatal("Could not locate authority for $peername");
}
my $query_result =
DBQueryFatal("select * from emulab_peers ".
"where name='$peername' or urn='$urn' or ".
" weburl=$safe_url");
fatal("Peer already exists. Please delete first")
if ($query_result->numrows);
fatal("Could not add new peer")
if (!DBQueryWarn("insert into emulab_peers set ".
" name='$peername', urn='$urn', weburl=$safe_url, ".
" is_primary='$primary'"));
return 0;
}
#
# Add a user.
#
sub AddUser(;$)
{
my ($token) = @_;
if (! defined($token)) {
usage()
if (! @ARGV);
$token = $ARGV[0];
}
my $user = User->Lookup($token);
if (!defined($user)) {
fatal("No such user");
}
my $uid_idx = $user->uid_idx();
my $uid = $user->uid();
# Check for existing export.
my $query_result =
DBQueryFatal("select * from user_exports ".
"where uid_idx='$uid_idx' and peer='$peername'");
if ($query_result->numrows && !$force) {
fatal("User already exported to peer. Use -f option");
}
my $urn = GeniHRN::Generate($OURDOMAIN, "user", $user->uid());
my $xmlgoo = emutil::ExecQuiet("$DUMPUSER $uid");
if ($?) {
print STDERR "$xmlgoo";
fatal("$DUMPUSER failed");
}
my $args = {"xmlstring" => $xmlgoo,
"urn" => $urn};
my $response = do_method($authority, "AddUser", $args);
fatal("Could not add user to $authority")
if (! (defined($response) &&
($response->code() == GENIRESPONSE_SUCCESS ||
$response->code() == GENIRESPONSE_ALREADYEXISTS)));
DBQueryFatal("replace into user_exports set ".
" uid='$uid', uid_idx='$uid_idx', peer='$peername', ".
" exported=now()");
return 0;
}
#
# Delete a user.
#
sub DeleteUser()
{
usage()
if (! @ARGV);
my $user = User->Lookup($ARGV[0]);
if (!defined($user)) {
fatal("No such user");
}
my $uid = $user->uid();
my $uid_idx = $user->uid_idx();
my $query_result =
DBQueryFatal("select * from user_exports ".
"where uid_idx='$uid_idx' and peer='$peername'");
if (!$query_result->numrows && !$force) {
fatal("User has not been exported to peer. Use -f option");
}
my $urn = GeniHRN::Generate($OURDOMAIN, "user", $user->uid());
my $args = {"urn" => $urn};
my $response = do_method($authority, "DeleteUser", $args);
fatal("Could not delete user from $authority")
if (! (defined($response) &&
($response->code() == GENIRESPONSE_SUCCESS ||
$response->code() == GENIRESPONSE_SEARCHFAILED)));
DBQueryFatal("delete from user_exports ".
"where uid_idx='$uid_idx' and peer='$peername'");
return 0;
}
#
# Modify a user.
#
sub ModifyUser()
{
usage()
if (! @ARGV);
my $user = User->Lookup($ARGV[0]);
if (!defined($user)) {
fatal("No such user");
}
my $uid = $user->uid();
my $uid_idx = $user->uid_idx();
my $query_result =
DBQueryFatal("select * from user_exports ".
"where uid_idx='$uid_idx' and peer='$peername'");
if (!$query_result->numrows && !$force) {
fatal("User has not been exported to peer. Use -f option");
}
my $urn = GeniHRN::Generate($OURDOMAIN, "user", $user->uid());
my $xmlgoo = emutil::ExecQuiet("$DUMPUSER $uid");
if ($?) {
fatal("$DUMPUSER failed");
}
my $args = {"xmlstring" => $xmlgoo,
"urn" => $urn};
my $response = do_method($authority, "ModifyUser", $args);
fatal("Could not modify user at $authority")
if (! (defined($response) &&
$response->code() == GENIRESPONSE_SUCCESS));
return 0;
}
#
# Set the groups for a user.
#
sub SetGroups(;$)
{
my ($token) = @_;
if (! defined($token)) {
usage()
if (! @ARGV);
$token = $ARGV[0];
}
my $user = User->Lookup($token);
if (!defined($user)) {
fatal("No such user");
}
my $uid = $user->uid();
my $uid_idx = $user->uid_idx();
my $query_result =
DBQueryFatal("select * from user_exports ".
"where uid_idx='$uid_idx' and peer='$peername'");
if (!$query_result->numrows && !$force) {
fatal("User has not been exported to peer. Use -f option");
}
my $urn = GeniHRN::Generate($OURDOMAIN, "user", $user->uid());
my @grouplist = ();
if ($user->GroupMembershipList(\@grouplist)) {
fatal("Could not get group list for user");
}
if (! @grouplist) {
print STDERR "$user is not a member of any groups";
return 0;
}
my %grouparray = ();
foreach my $group (@grouplist) {
my $pid_idx = $group->pid_idx();
my $gid_idx = $group->gid_idx();
#
# See if this group has been exported. Skip if not.
#
$query_result =
DBQueryFatal("select pid_idx,gid_idx from group_exports ".
"where pid_idx='$pid_idx' and gid_idx='$gid_idx' and ".
" peer='$peername'");
next
if (!$query_result->numrows);
my $membership = $group->LookupUser($user);
if (!defined($membership)) {
fatal("Could not get membership for $user in $group");
}
my $pid = $group->pid();
my $gid = $group->gid();
my $trust = $membership->trust();
$grouparray{"$pid,$gid"} = $trust;
}
print STDERR Dumper(\%grouparray) if ($debug);
my $args = {"groups" => \%grouparray,
"urn" => $urn};
my $response = do_method($authority, "SetGroups", $args);
fatal("Could not setgroups for user at $authority")
if (! (defined($response) &&
$response->code() == GENIRESPONSE_SUCCESS));
return 0;
}
#
# Cross Login
#
sub CrossLogin()
{
usage()
if (! @ARGV);
my $user = User->Lookup($ARGV[0]);
if (!defined($user)) {
fatal("No such user");
}
my $uid = $user->uid();
my $uid_idx = $user->uid_idx();
my $query_result =
DBQueryFatal("select * from user_exports ".
"where uid_idx='$uid_idx' and peer='$peername'");
if (!$query_result->numrows && !$force) {
fatal("User has not been exported to peer. Use -f option");
}
my $urn = GeniHRN::Generate($OURDOMAIN, "user", $user->uid());
my $args = {"urn" => $urn};
#
# Since this is coming from the web interface, want to limit
# how long we wait, and return status if timed out.
#
Genixmlrpc->SetTimeout(20);
my $response = do_method($authority, "CrossLogin", $args);
fatal("Could not xlogin user at $authority")
if (! (defined($response) &&
$response->code() == GENIRESPONSE_SUCCESS));
my $key = $response->value();
print "$key\n";
return 0;
}
#
# Add a Project
#
sub AddProject()
{
usage()
if (! @ARGV);
my $project = Project->Lookup($ARGV[0]);
if (!defined($project)) {
fatal("No such project");
}
my $pid = $project->pid();
my $pid_idx = $project->pid_idx();
my $leader_uid = $project->head_uid();
my $leader_idx = $project->head_idx();
my $query_result =
DBQueryFatal("select * from group_exports ".
"where pid_idx='$pid_idx' and gid_idx='$pid_idx' and ".
" peer='$peername'");
if ($query_result->numrows && !$force) {
fatal("Project has already been exported to peer. Use -f option");
}
#
# Check that the leader has been exported, and if not do that first.
#
my $leader_result =
DBQueryFatal("select * from user_exports ".
"where uid_idx='$leader_idx' and peer='$peername'");
if (!$leader_result->numrows) {
AddUser($leader_idx);
}
my $xmlgoo = emutil::ExecQuiet("$DUMPPROJ $pid");
if ($?) {
fatal("$DUMPPROJ failed");
}
my $args = {"xmlstring" => $xmlgoo};
my $response = do_method($authority, "AddProject", $args);
fatal("Could not add project to $authority")
if (! (defined($response) &&
($response->code() == GENIRESPONSE_SUCCESS ||
$response->code() == GENIRESPONSE_ALREADYEXISTS)));
DBQueryFatal("replace into group_exports set ".
" pid='$pid', pid_idx='$pid_idx', ".
" gid='$pid', gid_idx='$pid_idx', ".
" exported=now(), updated=now(), ".
" peer='$peername'");
SetGroups($leader_idx);
return 0;
}
#
# Add a Group
#
sub AddGroup()
{
usage()
if (! @ARGV);
my $group = Group->Lookup($ARGV[0]);
if (!defined($group)) {
fatal("No such group");
}
if ($group->IsProjectGroup()) {
fatal("Please use addproject instead.");
}
my $pid_idx = $group->pid_idx();
my $gid_idx = $group->gid_idx();
my $pid = $group->pid();
my $gid = $group->gid();
my $query_result =
DBQueryFatal("select * from group_exports ".
"where pid_idx='$pid_idx' and gid_idx='$pid_idx' and ".
" peer='$peername'");
if (!$query_result->numrows) {
fatal("Project has not been exported to peer.\n");
}
$query_result =
DBQueryFatal("select * from group_exports ".
"where pid_idx='$pid_idx' and gid_idx='$gid_idx' and ".
" peer='$peername'");
if ($query_result->numrows && !$force) {
fatal("Group has already been exported to peer. Use -f option");
}
my %tags = (
"project" => $group->pid(),
"group_id" => $group->gid(),
"group_leader" => $group->leader(),
"group_description" => $group->description() || "",
);
my $args = {"tags" => \%tags};
my $response = do_method($authority, "AddGroup", $args);
fatal("Could not add group to $authority")
if (! (defined($response) &&
($response->code() == GENIRESPONSE_SUCCESS ||
$response->code() == GENIRESPONSE_ALREADYEXISTS)));
DBQueryFatal("replace into group_exports set ".
" pid='$pid', pid_idx='$pid_idx', ".
" gid='$gid', gid_idx='$gid_idx', ".
" exported=now(), updated=now(), ".
" peer='$peername'");
return 0;
}
#
# Make an rpc call to the Emulab interface on the remote authority.
#
sub do_method($$;$)
{
my ($authority, $method, $args) = @_;
$args = {} if (!defined($args));
#
# The URL refers to the sa, but we want the emulab interface.
#
my $url = $authority->url();
$url =~ s/\/sa$/\/emulab/;
$args->{'credentials'} = [$credential->asString()];
my $response =
Genixmlrpc::CallMethod($url, undef, $method, $args);
if (!defined($response)) {
print STDERR "*** Internal error at $authority\n";
return undef;
}
if ($response->code() != GENIRESPONSE_SUCCESS) {
print STDERR "Error at $authority:";
print STDERR " " . $response->output() . "\n";
}
return $response;
}
sub fatal($) {
my ($msg) = @_;
print STDERR "$msg\n";
exit(-1);
}