Commit 7bcc61cb authored by Leigh Stoller's avatar Leigh Stoller

Export methods that interface to backend createdataset and deletelease

scripts. Also add a describe method.

In order to create a dataset, the caller must either be a local user, or
have an extra credential that grants the "blockstores" priv.

Like slivers, datasets are currently created in the holding project and
group corresponding the SA and subauthority.

Eventually need to add sharing control (say, to make a dataset globally
read only), but that does not exist in the backend yet.
parent 8af7871c
......@@ -3183,5 +3183,219 @@ sub ConsoleURL($)
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $url);
}
#
# Blockstore support.
#
my $CREATEDATASET = "$TB/bin/createdataset";
my $DELETEDATASET = "$TB/bin/deletelease";
sub CreateDataset($)
{
my ($argref) = @_;
my $credentials = $argref->{'credentials'};
my $size = $argref->{'size'}; # MiBs
my $dataset = $argref->{'name'};
require Lease;
if (! (defined($credentials) &&
defined($size) && defined($dataset))) {
return GeniResponse->MalformedArgsResponse("Missing arguments");
}
if ($size !~ /^\d+$/) {
return GeniResponse->MalformedArgsResponse("Bad size, use MiBs");
}
if ($dataset !~ /^[-\w]+$/) {
return GeniResponse->MalformedArgsResponse("Bad dataset name");
}
my ($credential,$speaksfor) = GeniStd::CheckCredentials($credentials);
return $credential
if (GeniResponse::IsResponse($credential));
#
# Only real local users can do blockstores, or the credential
# must include the correct priv.
#
my $user = GeniUser->Lookup($credential->owner_cert()->urn(), 1);
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN)
if (! ((defined($user) && $user->IsLocal()) ||
$credential->HasPrivilege("blockstores")));
# Get the project and group. This needs more thought.
my $group = GeniUtil::GetHoldingProject($user->urn(), $user);
return $group
if (GeniResponse::IsResponse($group));
my $lease = Lease->Lookup($group->pid(), $dataset);
if (defined($lease)) {
GeniResponse->Create(GENIRESPONSE_ALREADYEXISTS);
}
my $cmd = "$CREATEDATASET -b -s $size ";
if (exists($argref->{'type'})) {
my $type = $argref->{'type'};
return GeniResponse->MalformedArgsResponse("Bad type")
if ($type !~ /^[-\w]+$/);
$cmd .= " -t $type";
}
if (exists($argref->{'fstype'})) {
my $fstype = $argref->{'fstype'};
return GeniResponse->MalformedArgsResponse("Bad FS type")
if ($fstype !~ /^[-\w]+$/);
$cmd .= " -f $fstype";
}
if (exists($argref->{'expires'})) {
my $expiration = $argref->{'expires'};
# Gack, why does Frontier do this. It is stupid.
if (ref($expiration) eq 'Frontier::RPC2::DateTime::ISO8601') {
$expiration = $expiration->value;
}
if (!str2time($expiration)) {
return GeniResponse->MalformedArgsResponse("Bad expiration");
}
$cmd .= " -e '" . libtestbed::TBDateStringLocal($expiration) . "' ";
}
$cmd .= " " . $group->pid() . "/" . $dataset;
my $output = GeniUtil::ExecQuiet($cmd);
# Not a typical op, so always print debugging info;
print STDERR $output;
if ($?) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef, $output);
}
#
# Grab the lease to see if its been approved, we want to tell
# the user something.
#
my $lease = Lease->Lookup($group->pid(), $dataset);
if (!defined($lease)) {
print STDERR "Could not lookup lease after createdataset\n";
GeniResponse->Create(GENIRESPONSE_ERROR);
}
my $msg = undef;
if ($lease->state() eq "unapproved") {
if ($lease->locked()) {
$msg = "Your dataset is being allocated.";
}
else {
$msg = "Your dataset has not been approved yet. Watch for email";
}
}
my $blob = {
"state" => $lease->state(),
"uuid" => $lease->uuid(),
"busy" => $lease->locked() ? 1 : 0,
};
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $blob, $msg);
}
sub DeleteDataset($)
{
my ($argref) = @_;
my $credentials = $argref->{'credentials'};
my $dataset = $argref->{'name'};
require Lease;
if (! (defined($credentials) && defined($dataset))) {
return GeniResponse->MalformedArgsResponse("Missing arguments");
}
if ($dataset !~ /^[-\w]+$/) {
return GeniResponse->MalformedArgsResponse("Bad dataset name");
}
my ($credential,$speaksfor) = GeniStd::CheckCredentials($credentials);
return $credential
if (GeniResponse::IsResponse($credential));
#
# Only real local users can do blockstores, or the credential
# must include the correct priv.
#
my $user = GeniUser->Lookup($credential->owner_cert()->urn(), 1);
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN)
if (! ((defined($user) && $user->IsLocal()) ||
$credential->HasPrivilege("blockstores")));
# Get the project and group. This needs more thought.
my $group = GeniUtil::GetHoldingProject($user->urn(), $user);
return $group
if (GeniResponse::IsResponse($group));
my $lease = Lease->Lookup($group->pid(), $dataset);
if (!defined($lease)) {
GeniResponse->Create(GENIRESPONSE_SEARCHFAILED);
}
#
# Only the creator can delete the dataset.
#
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN)
if (0 && $user->uid() ne $lease->owner());
my $cmd = "$DELETEDATASET -b -f " . $group->pid() . "/" . $dataset;
my $output = GeniUtil::ExecQuiet($cmd);
# Not a typical op, so always print debugging info;
print STDERR $output;
if ($?) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef, $output);
}
return GeniResponse->Create(GENIRESPONSE_SUCCESS);
}
sub ExtendDataset($)
{
my ($argref) = @_;
my $credentials = $argref->{'credentials'};
return GeniResponse->Create(GENIRESPONSE_NOT_IMPLEMENTED);
}
sub DescribeDataset($)
{
my ($argref) = @_;
my $credentials = $argref->{'credentials'};
my $dataset = $argref->{'name'};
require Lease;
require Blockstore;
require libtestbed;
if (! (defined($credentials) && defined($dataset))) {
return GeniResponse->MalformedArgsResponse("Missing arguments");
}
if ($dataset !~ /^[-\w]+$/) {
return GeniResponse->MalformedArgsResponse("Bad dataset name");
}
my ($credential,$speaksfor) = GeniStd::CheckCredentials($credentials);
return $credential
if (GeniResponse::IsResponse($credential));
#
# Only real local users can do blockstores, or the credential
# must include the correct priv.
#
my $user = GeniUser->Lookup($credential->owner_cert()->urn(), 1);
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN)
if (! ((defined($user) && $user->IsLocal()) ||
$credential->HasPrivilege("blockstores")));
# Get the project and group. This needs more thought.
my $group = GeniUtil::GetHoldingProject($user->urn(), $user);
return $group
if (GeniResponse::IsResponse($group));
my $lease = Lease->Lookup($group->pid(), $dataset);
if (!defined($lease)) {
GeniResponse->Create(GENIRESPONSE_SEARCHFAILED);
}
my $blob = {};
$blob->{'state'} = $lease->state();
$blob->{'type'} = $lease->type();
$blob->{"busy"} = $lease->locked() ? 1 : 0;
$blob->{'created'} = libtestbed::TBDateStringGMT($lease->inception());
$blob->{'expires'} = libtestbed::TBDateStringGMT($lease->lease_end());
$blob->{'lastused'} = libtestbed::TBDateStringGMT($lease->last_used());
my $bstore = Blockstore->LookupByLease($lease->idx());
if (defined($bstore)) {
$blob->{'size'} = $bstore->total_size();
}
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $blob);
}
# _Always_ make sure that this 1 is at the end of the file...
1;
......@@ -108,6 +108,9 @@ elsif ($GENI_VERSION eq "2.0") {
"UnShareLan" => \&GeniCMV2::UnShareLan,
"ListActiveSlivers" => \&GeniCMV2::ListActiveSlivers,
"ConsoleURL" => \&GeniCMV2::ConsoleURL,
"CreateDataset" => \&GeniCMV2::CreateDataset,
"DeleteDataset" => \&GeniCMV2::DeleteDataset,
"DescribeDataset" => \&GeniCMV2::DescribeDataset,
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment