ptopgen_new.in 6.99 KB
Newer Older
1 2 3
#!/usr/bin/perl -w

#
4
# Copyright (c) 2000-2012 University of Utah and the Flux Group.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# 
# {{{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/>.
# 
# }}}
24 25 26 27 28 29
#

use strict;
use English;
use Getopt::Std;

30
use lib "@prefix@/lib";
31
use libdb;
32
use emdbi;
33
use libptop_new;
34 35
use GeniXML;

36
sub usage();
37 38 39 40
sub processArgs();
sub consultDatabase();
sub process();
sub printResults();
41
sub printTypeLimits($);
42 43 44 45 46 47

#
# Turn off line buffering on output
#
$| = 1;

48
my $print_xml = 0;
49
my $print_ns = $GeniXML::RSPEC_2_NS;
50
my $typelimitfile;
51
my $debug = 0;
52

53
# Initialize permissions table for the current project
54
emdbi::ClearQueryCount();
55 56 57
processArgs();
consultDatabase();
printResults();
58 59 60
if ($debug) {
    print STDERR "# of Queries: " . emdbi::GetQueryCount() . "\n";
}
61

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
sub usage()
{
    print("Usage: ptopgen [-p pid [-e eid]] [-v] [-r] [-S] [-s switch]\n".
	  "               [-h] [-a] [-m multiplex_factor] [-u] [-d]\n".
	  "               [-c delay_capacity] [-x] [-g (0.1 | 0.2 | 2)]\n".
	  "               [-l type-limit-file] [-1 component_name]\n\n" .
	  "       -p User project. May restrict nodes and osids.\n".
	  "       -e User experiment. Nodes and bandwidth allocated to\n" .
	  "          this experiment are reported as free.\n" .
	  "       -v Include virtual node types\n".
	  "       -r Include widearea nodes\n".
	  "       -S Include simulated node types and flags\n".
	  "       -s Switch to use (UNIMPLEMENTED)\n".
	  "       -h Include shared nodes\n".
	  "       -a Include reserved nodes\n".
	  "       -m Override multiplex_factor\n".
	  "       -u Prune unused interfaces of allocated nodes (-e)(UNIMPLEMENTED)\n".
79
	  "       -d Debug mode prints any problems in the database".
80 81 82 83
	  "       -c Override delay capacity\n".
	  "       -x Output in an RSpec xml format\n".
	  "       -g version With -x, geni version. Must be '0.1', '0.2' or '2'\n".
	  "       -l specifies the location of the type limit file\n" .
84
          "       -1 Print an rspec containing only the node component-name");
85 86 87
        exit(-1);
}

88 89
sub processArgs()
{
90 91 92 93
    #
    # Parse command arguments. Once we return from getopts, all that should be
    # left are the required arguments.
    #
94
    my $optlist = "p:e:vrSs:ham:udc:xg:l:1:C";
95 96 97 98 99 100 101
    my %options = ();
    if (! getopts($optlist, \%options)) {
	usage();
    }
    if (@ARGV) {
	usage();
    }
102 103 104
    if (defined($options{"s"})) {
	die("-s (switchtouse) option is not implemented\n");
    }
105 106
    if (defined($options{"x"})) {
	$print_xml = 1;
107
	if (! $libptop_new::PGENISUPPORT) {
108 109 110 111 112 113 114 115 116 117
	    usage();
	}
	my $mode = $options{"g"};
	if (defined($mode)) {
	    if ($mode eq "0.1") {
		$print_ns = $GeniXML::RSPEC_0_1_NS;
	    } elsif ($mode eq "0.2") {
		$print_ns = $GeniXML::RSPEC_0_2_NS;
	    } elsif ($mode eq "2") {
		$print_ns = $GeniXML::RSPEC_2_NS;
118 119
	    } elsif ($mode eq "3") {
		$print_ns = $GeniXML::RSPEC_3_NS;
120 121 122 123 124 125 126 127
	    } else {
		usage();
	    }
	}
    }
    if (defined($options{"l"})) {
	$typelimitfile = $options{"l"};
    }
128 129 130
    if (defined($options{"d"})) {
	$debug = 1;
    }
131
    libptop_new::ProcessArgs(\%options);
132 133 134 135 136
}

sub consultDatabase()
{
    # Bulk lookup on nodes table
137
    libptop_new::LookupNodes();
138

139
    # Bulk lookup of permissions table for project
140
    libptop_new::LookupPermissions();
141 142

    # Bulk lookup of global usage counts for shared nodes
143
    libptop_new::LookupGlobalCounts();
144 145

    # Bulk lookup of node and node_type auxtypes
146
    libptop_new::LookupAuxtypes();
147 148

    # Bulk lookup of node and node_type features
149
    libptop_new::LookupFeatures();
150

151
    # Bulk lookup of osids for features and genimode
152
    libptop_new::LookupOsids();
153

154
    # Bulk lookup of interfaces
155
    libptop_new::LookupInterfaces();
156 157

    # Bulk lookup of wires
158
    libptop_new::LookupLinks();
159

160
    # Process each node adding ptypes and features
161
    foreach my $current (values(%{ libptop_new::Nodes() })) {
162
	if ($current->willPrint()) {
163
	    $current->processTypeFeatures();
164 165 166 167 168
	    $current->processSwitch();
	    $current->processLocal();
	    $current->processWidearea();
	}
    }
169 170

    libptop_new::AddFakeNodes();
171 172 173 174 175 176
}

sub printResults()
{
    my $doc = GeniXML::CreateDocument($print_ns, "rspec");
    my $rspec = $doc->documentElement();
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
    $rspec->setNamespace($GeniXML::XSI_NS, "xsi", 0);
    if (! GeniXML::IsVersion0($rspec)) {
	$rspec->setNamespace($GeniXML::EMULAB_NS, "emulab", 0);
	my $ns = $GeniXML::RSPEC_2_NS;
	my $emulabns = $GeniXML::EMULAB_NS;
	my $emulaburl = "http://www.protogeni.net/resources/rspec/ext/emulab/1/ptop_extension.xsd";
	$rspec->setAttributeNS($GeniXML::XSI_NS, "xsi:schemaLocation",
			       "$ns $ns/ad.xsd $emulabns $emulaburl");
	#	if (defined($MAINSITE) && $MAINSITE) {
	#	    Add stitching namespace and schemaLocation
	#	}
    }
    $rspec->setAttribute("type", "advertisement");
    my @times = gmtime(time());
    my $generated = sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ",
			    $times[5] + 1900, $times[4] + 1, $times[3],
			    $times[2], $times[1], $times[0]);
    $rspec->setAttribute("generated", $generated);
    my $expiration = sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ",
			     $times[5] + 1900, $times[4] + 1, $times[3],
			     $times[2], $times[1], $times[0]);
    if (GeniXML::IsVersion0($rspec)) {
	$rspec->setAttribute("valid_until", $expiration);
    } else {
	$rspec->setAttribute("expires", $expiration);
    }
    
204
    foreach my $current (values(%{ libptop_new::Nodes() })) {
205 206 207 208 209 210 211 212
	if ($current->willPrint()) {
	    if ($print_xml) {
		$current->toXML($rspec);
	    } else {
		print $current->toString()."\n";
	    }
	}
    }
213
    foreach my $current (values(%{ libptop_new::Links() })) {
214 215 216 217 218 219 220 221
	if ($current->willPrint()) {
	    if ($print_xml) {
		$current->toXML($rspec);
	    } else {
		print $current->toString()."\n";
	    }
	}
    }
222
    printTypeLimits($rspec);
223 224 225 226
    if ($print_xml) {
	print GeniXML::Serialize($rspec, 1)."\n";
    }
}
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251

sub printTypeLimits($)
{
    my ($rspec) = @_;
    if (defined($typelimitfile)) {
	open(TYPELIMIT, "<$typelimitfile") or 
	    die("Count not open type limit file $typelimitfile\n");
	my @typelimits = <TYPELIMIT>;
	close(TYPELIMIT);

	foreach my $line (@typelimits) { 
	    chomp($line);
	    my ($typeclass, $count) = split(" ", $line);
	    
	    if ($print_xml && ! GeniXML::IsVersion0($rspec)) {
		my $limit = GeniXML::AddElement("set_type_limit", $rspec,
						$GeniXML::EMULAB_NS);
		GeniXML::SetText("typeclass", $limit, $typeclass);
		GeniXML::SetText("count", $limit, $count);
	    } else {
		print "set-type-limit $typeclass $count\n";
	    }
	}
    }
}