From 3b673271b4dd950688946d5d9e4ff4cafa0e0244 Mon Sep 17 00:00:00 2001 From: Gary Wong Date: Fri, 18 Mar 2011 11:20:49 -0600 Subject: [PATCH] Add rmblob facility (allowing blob owners to remove their blobs). --- sql/database-create.sql | 1 + sql/updates/4/236 | 19 +++++++++ utils/GNUmakefile.in | 2 +- utils/mkblob.in | 16 ++++++-- utils/rmblob.in | 82 +++++++++++++++++++++++++++++++++++++ xmlrpc/GNUmakefile.in | 2 +- xmlrpc/emulabserver.py.in | 24 ++++++++++- xmlrpc/script_wrapper.py.in | 41 ++++++++++++++++++- 8 files changed, 179 insertions(+), 8 deletions(-) create mode 100644 sql/updates/4/236 mode change 100644 => 100755 utils/mkblob.in create mode 100755 utils/rmblob.in diff --git a/sql/database-create.sql b/sql/database-create.sql index 392f93d4b..1b9aaa1cf 100644 --- a/sql/database-create.sql +++ b/sql/database-create.sql @@ -128,6 +128,7 @@ DROP TABLE IF EXISTS `blobs`; CREATE TABLE `blobs` ( `uuid` varchar(40) NOT NULL, `filename` tinytext, + `owner_uid` varchar(8) NOT NULL default '', PRIMARY KEY (`uuid`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; diff --git a/sql/updates/4/236 b/sql/updates/4/236 new file mode 100644 index 000000000..972e54d37 --- /dev/null +++ b/sql/updates/4/236 @@ -0,0 +1,19 @@ +# +# Add owner uid to blob table (to allow rmblob) +# +use strict; +use libdb; + +sub DoUpdate($$$) +{ + my ($dbhandle, $dbname, $version) = @_; + + if( !DBSlotExists( "blobs", "owner_uid" ) ) { + DBQueryFatal( "ALTER TABLE blobs ADD " . + "`owner_uid` varchar(8) NOT NULL default ''" ); + } + + return 0; +} + +1; diff --git a/utils/GNUmakefile.in b/utils/GNUmakefile.in index b5efed84e..674a7c345 100644 --- a/utils/GNUmakefile.in +++ b/utils/GNUmakefile.in @@ -17,7 +17,7 @@ SUBDIRS = nsgen BIN_SCRIPTS = delay_config sshtb create_image node_admin link_config \ setdest loghole webcopy linkmon_ctl snmp-if-deref.sh \ template_record spewevents \ - wbts_dump mkblob + wbts_dump mkblob rmblob SBIN_SCRIPTS = vlandiff vlansync withadminprivs export_tables cvsupd.pl \ eventping grantnodetype import_commitlog daemon_wrapper \ opsreboot deletenode node_statewait grabwebcams \ diff --git a/utils/mkblob.in b/utils/mkblob.in old mode 100644 new mode 100755 index 4ade53bbf..4e1cf0371 --- a/utils/mkblob.in +++ b/utils/mkblob.in @@ -36,15 +36,23 @@ use libtestbed; # Handle command-line options. # sub usage() { - print STDERR "Usage: $0 \n"; + print STDERR "Usage: $0 \n"; exit( 1 ); } -usage() unless @ARGV == 1; -my ( $filename ) = @ARGV; +usage() unless @ARGV == 2; +my ( $uid, $filename ) = @ARGV; # # Must taint check! # +if ($uid =~ /^([-\w #%&*+,.\/:;=?@\[\\\]^{|}]+)$/) { + $uid = $1; +} +else { + print STDERR "Bad character in uid\n"; + exit( 1 ); +} + if ($filename =~ /^([-\w #%&*+,.\/:;=?@\[\\\]^{|}]+)$/) { $filename = $1; } @@ -59,7 +67,7 @@ my $uuid = `@UUIDGEN@`; chomp $uuid; my $result = DBQueryWarn( "INSERT INTO blobs SET uuid='$uuid', " . - "filename='$filename';" ); + "filename='$filename', owner_uid='$uid';" ); unless( $result ) { print STDERR "Could not insert record.\n"; exit( 1 ); diff --git a/utils/rmblob.in b/utils/rmblob.in new file mode 100755 index 000000000..e2be1b400 --- /dev/null +++ b/utils/rmblob.in @@ -0,0 +1,82 @@ +#!/usr/bin/perl -w + +# +# EMULAB-COPYRIGHT +# Copyright (c) 2010 University of Utah and the Flux Group. +# All rights reserved. +# + +use English; +use strict; + +# +# Configure variables +# +my $TB = "@prefix@"; + +# +# Turn off line buffering on output +# +$| = 1; + +# +# Untaint the path +# +$ENV{'PATH'} = "$TB/bin:$TB/sbin:/bin:/usr/bin:/sbin:/usr/sbin"; +delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; + +# +# Testbed Support libraries +# +use lib "@prefix@/lib"; +use libdb; +use libtestbed; + +# +# Handle command-line options. +# +sub usage() { + print STDERR "Usage: $0 \n"; + exit( 1 ); +} + +usage() unless @ARGV == 2; +my ( $uid, $uuid ) = @ARGV; +# +# Must taint check! +# +if ($uid =~ /^([-\w #%&*+,.\/:;=?@\[\\\]^{|}]+)$/) { + $uid = $1; +} +else { + print STDERR "Bad character in uid\n"; + exit( 1 ); +} + +if ($uuid =~ /^([-\w]+)$/) { + $uuid = $1; +} +else { + print STDERR "Bad character in uuid\n"; + exit( 1 ); +} + +my $result = DBQueryWarn( "DELETE FROM blobs WHERE uuid='$uuid' AND " . + "owner_uid='$uid';" ); +unless( $result ) { + print STDERR "Could not delete record.\n"; + exit( 1 ); +} + +unless( $result->affectedrows == 1 ) { + print STDERR "Permission denied.\n"; + exit( 1 ); +} + +# And clean up the blob_files table (which is only a cache), just in case +# we removed the last reference to a file. +DBQueryWarn( "DELETE blob_files FROM blob_files LEFT OUTER JOIN blobs ON " . + "blob_files.filename=blobs.filename WHERE " . + "blobs.filename IS NULL;" ); + +exit( 0 ); diff --git a/xmlrpc/GNUmakefile.in b/xmlrpc/GNUmakefile.in index 3fd254f48..2c7d086e7 100644 --- a/xmlrpc/GNUmakefile.in +++ b/xmlrpc/GNUmakefile.in @@ -35,7 +35,7 @@ SYMLINKS = node_admin node_reboot os_load create_image node_list \ modexp expinfo node_avail tbuisp expwait template_commit \ template_export template_swapin template_swapout \ template_stoprun template_instantiate template_startrun \ - template_checkout node_avail_list mkblob + template_checkout node_avail_list mkblob rmblob # # Force dependencies on the scripts so that they will be rerun through diff --git a/xmlrpc/emulabserver.py.in b/xmlrpc/emulabserver.py.in index 177f95126..3a33c5516 100755 --- a/xmlrpc/emulabserver.py.in +++ b/xmlrpc/emulabserver.py.in @@ -5748,7 +5748,29 @@ class blob: if (argerror): return argerror - (exitval, output) = runcommand( TBDIR + "/bin/mkblob " + argdict[ "filename" ] ) + (exitval, output) = runcommand( TBDIR + "/bin/mkblob " + self.uid + " " + argdict[ "filename" ] ) + + if exitval: + return EmulabResponse( RESPONSE_ERROR, exitval >> 8, output=output ) + else: + return EmulabResponse( RESPONSE_SUCCESS, value=0, output=output ) + + def rmblob( self, version, argdict ): + if version != self.VERSION: + return EmulabResponse(RESPONSE_BADVERSION, + output="Client version mismatch!") + + try: + checknologins() + pass + except NoLoginsError, e: + return EmulabResponse(RESPONSE_REFUSED, output=str(e)) + + argerror = CheckRequiredArgs(argdict, ("uuid",)) + if (argerror): + return argerror + + (exitval, output) = runcommand( TBDIR + "/bin/rmblob " + self.uid + " " + argdict[ "uuid" ] ) if exitval: return EmulabResponse( RESPONSE_ERROR, exitval >> 8, output=output ) diff --git a/xmlrpc/script_wrapper.py.in b/xmlrpc/script_wrapper.py.in index 699d4015e..1a48a8d75 100755 --- a/xmlrpc/script_wrapper.py.in +++ b/xmlrpc/script_wrapper.py.in @@ -150,7 +150,9 @@ API = { "template_stoprun" : { "func" : "template_stoprun", "help" : "Stop current experiment run" }, "mkblob" : { "func" : "mkblob", - "help" : "Create a new blob in the blob store" } + "help" : "Create a new blob in the blob store" }, + "rmblob" : { "func" : "rmblob", + "help" : "Remove a blob from the blob store" } }; # @@ -2640,6 +2642,43 @@ class mkblob: return pass +# +# rmblob +# +class rmblob: + def __init__(self, argv=None): + self.argv = argv; + return + + def apply(self): + try: + opts, req_args = getopt.getopt(self.argv, "h", [ "help" ]); + pass + except getopt.error, e: + print e.args[0] + self.usage(); + return -1; + + for opt, val in opts: + if opt in ("-h", "--help"): + self.usage() + return 0 + + # Do this after so --help is seen. + if len(req_args) != 1: + self.usage(); + return -1; + + rval,response = do_method( "blob", "rmblob", + { "uuid" : req_args[ 0 ] } ); + return rval; + + def usage(self): + print "rmblob [options] uuid" + wrapperoptions(); + return + pass + # # Infer template guid from path # -- GitLab