Commit b7fb16a8 authored by Leigh Stoller's avatar Leigh Stoller

Various bits of support for issue #408:

* Add portal url to the existing emulab extension that tells the CM the
  CreateSliver() is coming from the Portal. Always send this info, not
  just for the Emulab Portal.

* Stash that info in the geni slice data structure so we can add links
  back to the portal status page for current slices.

* Add routines to generate a portal URL for the history entries, since
  we will not have those links for historical slices. Add links back to
  the portal on the showslice and slice history pages.
parent 108d3d6f
......@@ -1533,16 +1533,16 @@ sub EncryptBlocks($$$)
#
# Add a portal element.
#
sub AddPortalTag($$$)
sub AddPortalTag($$$$)
{
my ($pxml, $tag, $pmsg) = @_;
my ($pxml, $tag, $url, $pmsg) = @_;
my $rspec = GeniXML::Parse($$pxml);
if (! defined($rspec)) {
$$pmsg = "AddPortalTag: Could not parse rspec";
return -1;
}
GeniXML::SetPortal($rspec, $tag);
GeniXML::SetPortal($rspec, $tag, $url);
$$pxml = GeniXML::Serialize($rspec);
return 0;
}
......
......@@ -825,20 +825,6 @@ $tmp = APT_Profile::EncryptBlocks(\$rspecstr, $alt_certificate, \$errmsg);
if ($tmp) {
($tmp < 0 ? fatal($errmsg) : UserError($errmsg));
}
#
# Tell the CM to do normal NFS mounts if this is the "Emulab" portal
# making the request. The CM is of course free to ignore this.
#
# XXX Need to handle this differently if we use the stitcher.
#
if ($portal ne "emulab") {
if (APT_Profile::ClearPortalTag(\$rspecstr, $errmsg)) {
fatal($errmsg);
}
}
elsif (APT_Profile::AddPortalTag(\$rspecstr, $portal, $errmsg)) {
fatal($errmsg);
}
#
# Generate credentials we need.
......@@ -897,6 +883,22 @@ if ($instance->ApplyExtensionPolicies()) {
fatal("Error applying policies");
}
#
# Tell the CM the portal information, which is used by Emulab based
# CMs to send email links.
#
# Special: This also tells the CM to do normal NFS mounts if this is
# the "Emulab" portal making the request.
#
# XXX The local instance will not have these tags, but no big deal.
# XXX Need to handle this differently if we use the stitcher?
#
if (APT_Profile::AddPortalTag(\$rspecstr,
$portal, $instance->webURL(), \$errmsg)) {
$instance->Delete();
fatal($errmsg);
}
#
# Get the set of keys (accounts) that need to be sent along. We build
# them in CM format, but convert to AM format later if needed.
......
......@@ -1022,6 +1022,17 @@ sub GetTicketAuxAux($)
$virtexperiment->nfsmounts("emulabdefault");
}
}
# Record this info for local email about these slices.
my ($portal_tag,$portal_url) = GeniXML::GetPortal($rspec);
if (defined($portal_tag) && $portal_tag ne "" &&
$portal_tag =~ /^([-\w]+)$/) {
$slice->SetPortalTag($portal_tag);
}
if (defined($portal_url) && $portal_url ne "" &&
TBcheck_dbslot($portal_url, "default", "tinytext",
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR)) {
$slice->SetPortalURL($portal_url);
}
#
# An rspec is a structure that requests specific nodes. If those
......
......@@ -332,6 +332,8 @@ sub description($) { return field($_[0], "description"); }
sub async_mode($) { return field($_[0], "async_mode"); }
sub async_code($) { return field($_[0], "async_code"); }
sub async_output($) { return field($_[0], "async_output"); }
sub portal_tag($) { return field($_[0], "portal_tag"); }
sub portal_url($) { return field($_[0], "portal_url"); }
sub cert($) { return $_[0]->{'CERT'}->cert(); }
sub GetCertificate($) { return $_[0]->{'CERT'}; }
sub LOCKED($) { return $_[0]->{'LOCKED'}; }
......@@ -1568,6 +1570,78 @@ sub AddGenericCert($$$)
return DBQueryWarn($query);
}
sub SetPortalTag($$)
{
my ($self, $tag) = @_;
my $uuid = $self->uuid();
my $safe_tag = DBQuoteSpecial($tag);
return -1
if (!DBQueryWarn("update geni_slices set portal_tag=$safe_tag " .
"where uuid='$uuid'"));
$self->{'SLICE'}->{'portal_tag'} = $tag;
return 0;
}
sub SetPortalURL($$)
{
my ($self, $url) = @_;
my $uuid = $self->uuid();
my $safe_url = DBQuoteSpecial($url);
return -1
if (!DBQueryWarn("update geni_slices set portal_url=$safe_url " .
"where uuid='$uuid'"));
$self->{'SLICE'}->{'portal_url'} = $url;
return 0;
}
# Turn the URN into an experiment ID at the Portal.
sub portal_eid($)
{
my ($self) = @_;
my $urn = $self->urn();
return undef
if (!defined($self->portal_tag()));
my $eid = $urn->id();
$eid = $urn->project() . "/" . $eid if (defined($urn->project()));
return $eid;
}
#
# Generate a Portal URL.
#
sub GetPortalURL($)
{
my ($self) = @_;
my $portal_url;
return $self->portal_url()
if (defined($self->portal_url()));
my $speaker = $self->speaksfor_urn();
return undef
if (!defined($speaker));
return undef
if (! ($speaker->domain() eq $OURDOMAIN ||
$speaker->domain() eq "emulab.net"));
if ($speaker->domain() eq $OURDOMAIN) {
$portal_url = "$TBBASE/portal/";
}
else {
$portal_url = "https://www.emulab.net/portal/";
}
$portal_url .= "status.php?uuid=" . $self->uuid();
return $portal_url;
}
##########################################################################
#
package GeniSlice::ClientSliver;
......
......@@ -1131,15 +1131,28 @@ sub FromEmulabPortal($)
}
return 0;
}
sub SetPortal($$)
sub GetPortal($)
{
my ($rspec, $portal) = @_;
my ($rspec) = @_;
my $element = FindNodesNS("n:portal", $rspec, $EMULAB_NS)->pop();
if (!defined($element)) {
return undef;
}
my $tag = GetText("name", $element);
my $url = GetText("url", $element);
return ($tag, $url);
}
sub SetPortal($$$)
{
my ($rspec, $portal, $url) = @_;
my $element = FindNodesNS("n:portal", $rspec, $EMULAB_NS)->pop();
if (!defined($element)) {
$element = AddElement("portal", $rspec, $EMULAB_NS);
}
SetText("name", $element, $portal);
SetText("url", $element, $url);
return 0;
}
sub ClearPortal($)
......
<?php
#
# Copyright (c) 2006-2013 University of Utah and the Flux Group.
# Copyright (c) 2006-2018 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -129,7 +129,10 @@ class GeniSlice
function needsfirewall(){ return $this->field('needsfirewall'); }
function monitor_pid() { return $this->field('monitor_pid'); }
function expiration_max() { return $this->field('expiration_max'); }
function speaksfor_urn(){ return $this->field('speaksfor_urn'); }
function renew_limit() { return $this->field('renew_limit'); }
function portal_tag() { return $this->field('portal_tag'); }
function portal_url() { return $this->field('portal_url'); }
#
# Class function to return a list of all slices.
......@@ -575,4 +578,32 @@ class QuickVM
return QuickVM::Lookup($uuid);
}
}
#
# Generate a Portal URL.
#
function GenPortalURL($active, $urn, $slice_uuid)
{
global $OURDOMAIN, $TBBASE;
if (! (preg_match("/^[^+]*\+([^+]+)\+([^+]+)\+(.+)$/",
$urn, $matches) &&
($matches[1] == $OURDOMAIN || $matches[1] == "emulab.net"))) {
return null;
}
$domain = $matches[1];
if ($domain == $OURDOMAIN) {
$portal_url = "$TBBASE/portal/";
}
else {
$portal_url = "https://www.emulab.net/portal/";
}
if ($active) {
$portal_url .= "status.php?slice_uuid=$slice_uuid";
}
else {
$portal_url .= "memlane.php?slice_uuid=$slice_uuid";
}
return $portal_url;
}
?>
<?php
#
# Copyright (c) 2000-2015 University of Utah and the Flux Group.
# Copyright (c) 2000-2015, 2018 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -126,7 +126,7 @@ if (1) {
}
}
$query_result =
DBQueryFatal("select a.*,c.DN,s.idx as slice_idx ".
DBQueryFatal("select a.*,c.DN,s.portal_url,s.idx as slice_idx ".
" from aggregate_history as a ".
"left join geni_slices as s on s.uuid=a.slice_uuid ".
"left join geni_certificates as c on ".
......@@ -135,15 +135,20 @@ if (1) {
"order by a.idx desc limit 20",
$dblink);
$table = array('#id' => 'aggregate',
'#title' => "Aggregate History",
'#headings' => array("idx" => "ID",
"slice_hrn" => "Slice",
"creator_hrn" => "Creator",
"created" => "Created",
"Destroyed" => "Destroyed",
"Manifest" => "Manifest"));
$rows = array();
echo "<center>\n";
echo "<br>";
echo "<font size=+1><b>Aggregate History</b></font>";
echo "<br>\n";
echo "<table>\n";
echo " <thead>\n";
echo " <tr>\n";
echo " <th>ID</th>\n";
echo " <th>Slice/Creator</th>\n";
echo " <th>Created/Destroyed</th>\n";
echo " <th>Manifest/Portal</th>\n";
echo " </tr>\n";
echo " </thead>\n";
echo " <tbody>\n";
if (mysql_num_rows($query_result)) {
while ($row = mysql_fetch_array($query_result)) {
......@@ -158,6 +163,7 @@ if (1) {
$created = $row["created"];
$destroyed = $row["destroyed"];
$DN = $row["DN"];
$portal_url = "&nbsp";
# If we have urns, show those instead.
$slice_info = $slice_hrn;
......@@ -189,19 +195,38 @@ if (1) {
$url .= "$slice_info</a>";
$manifest_url = "<a href='manifesthistory.php?uuid=$uuid'>manifest</a>";
#
# Try to form a URL back to the (Utah) Portal.
#
if ($row["portal_url"]) {
$tmp = $row["portal_url"];
$portal_url = "<a href='$tmp'>portal</a>";
}
elseif ($row["speaksfor_urn"] && $row["speaksfor_urn"] != "") {
$active = ($destroyed ? 0 : 1);
$tmp = GenPortalURL($active,
$row["speaksfor_urn"], $slice_uuid);
if ($tmp) {
$portal_url = "<a href='$tmp'>portal</a>";
}
}
echo "<tr>";
echo " <td rowspan=2>$idx</td>";
echo " <td>$url</td>";
echo " <td>$created</td>";
echo " <td>$manifest_url</td>";
echo "</tr>";
echo "<tr>";
echo " <td>$creator_info</td>";
echo " <td>$destroyed</td>";
echo " <td>$portal_url</td>";
echo "</tr>";
$tablerow = array("idx" => $idx,
"hrn" => $url,
"creator" => $creator_info,
"created" => $created,
"destroyed" => $destroyed,
"manifest" => $manifest_url );
$rows[] = $tablerow;
$myindex = $idx;
}
list ($html, $button) = TableRender($table, $rows);
echo $html;
echo "</tbody>\n";
echo "</table>\n";
echo "</center>\n";
$query_result =
DBQueryFatal("select count(*) from aggregate_history as a ".
......
<?php
#
# Copyright (c) 2000-2015 University of Utah and the Flux Group.
# Copyright (c) 2000-2018 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -101,6 +101,20 @@ if ($slice->publicid()) {
$rows[] = array("Public URL" => "<a href='$url'>https:// ...</a>");
}
if ($slice->portal_tag()) {
$rows[] = array("Portal" => $slice->portal_tag());
if ($slice->portal_url()) {
$url = $slice->portal_url();
$rows[] = array("Portal URL" => "<a href='$url'>https:// ...</a>");
}
}
elseif ($slice->speaksfor_urn()) {
$portal_url = GenPortalURL(1, $slice->speaksfor_urn(), $slice->uuid());
if ($portal_url) {
$rows[] = array("Portal URL" =>
"<a href='$portal_url'>https:// ...</a>");
}
}
if (($manifest = $slice->GetManifest())) {
$popups[] = GeneratePopupDiv("manifest$manifestidx", $manifest);
$rows[] = array("manifest" =>
......
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