Commit 9d24ebe2 authored by Matt Strum's avatar Matt Strum Committed by Gary Wong

Small fixes and improvements.

Added ability to force AM API for managers, help button on the login page since that seems to be a source of confusion, live updating of the slice/slivers expires time so it reflects the actual time left instead of how much time was left the last time it was checked, global checkbox for creating private or global images.

AM API v3 support has started. So far the client is able to list resources at a manager. More work will need to be done to support the new create workflow now that it supports a two-phased commit similar to the CM API.

Fixed user being able to create a link while the slice is locked (having calls made), crash when user comes in with a credential rather than using a slice authority, and new slice button being shown even if user can't create slices.
parent 5649f98c
......@@ -173,6 +173,26 @@ package com.flack.geni
}
}
public static function getForceAmApi():Boolean
{
var forceAmApi:Boolean = false;
if(SharedCache._sharedObject != null && SharedCache._sharedObject.data.forceAmApi != null)
{
forceAmApi = SharedCache._sharedObject.data.forceAmApi;
}
return forceAmApi;
}
public static function setForceAmApi(value:Boolean):void
{
if(SharedCache._sharedObject != null)
{
SharedCache._sharedObject.data.forceAmApi = value;
}
}
// Manual managers
public static function wasManagerManuallyAdded(manager:GeniManager):Boolean
{
......
......@@ -60,7 +60,8 @@ package com.flack.geni
{
public static const becomeUserUrl:String = "http://www.protogeni.net/trac/protogeni/wiki/FlackManual#BecomingaUser";
public static const manualUrl:String = "http://www.protogeni.net/trac/protogeni/wiki/FlackManual";
public static const tutorialUrl:String = "https://www.protogeni.net/trac/protogeni/wiki/FlackTutorial";
public static const tutorialUrl:String = "http://www.protogeni.net/trac/protogeni/wiki/FlackTutorial";
public static const tutorialLoginUrl:String = "http://www.protogeni.net/trac/protogeni/wiki/FlackManual#LoggingIn";
public static const sshKeysSteps:String = "http://www.protogeni.net/trac/protogeni/wiki/Tutorial#UploadingSSHKeys";
// Portal
......
......@@ -75,7 +75,7 @@ IN THE WORK.
{
if(GeniMain.geniUniverse != null)
{
enabled = GeniMain.geniUniverse.user.HasCredential;
enabled = GeniMain.geniUniverse.user.HasCredential && GeniMain.geniUniverse.user.authority != null;
}
else
enabled = false;
......
......@@ -61,6 +61,7 @@ package com.flack.geni.display
import com.flack.shared.utils.ColorUtil;
import com.flack.shared.utils.ImageUtil;
import com.flack.shared.utils.ViewUtil;
import com.flack.geni.display.windows.AddAuthorityWindow;
public class DisplayUtil
{
......
......@@ -39,7 +39,7 @@ IN THE WORK.
<fx:Script>
<![CDATA[
import com.flack.geni.GeniMain;
import com.flack.geni.display.ChooseManagerWindow;
import com.flack.geni.display.windows.ChooseManagerWindow;
import com.flack.geni.plugins.emulab.FirewallSliverType;
import com.flack.geni.plugins.emulab.RawPcSliverType;
import com.flack.geni.resources.SliverTypes;
......
......@@ -221,6 +221,27 @@ IN THE WORK.
return _slice;
}
private var _timer:Timer;
public function onTimer(event:TimerEvent):void
{
updateSliversExpires();
}
public function initTimer():void
{
_timer = new Timer(1000);
_timer.addEventListener(TimerEvent.TIMER, onTimer);
_timer.start();
}
public function destroyTimer():void
{
if(_timer != null)
{
_timer.reset();
_timer.removeEventListener(TimerEvent.TIMER, onTimer);
_timer = null;
}
}
public function loadComponentsAreaFor(s:Slice):void
{
var currentArea:IComponentsArea = ComponentsArea;
......@@ -278,16 +299,15 @@ IN THE WORK.
SharedMain.sharedDispatcher.addEventListener(FlackEvent.CHANGED_SLICE, sliceChanged);
}
override public function initEvents():void
{
initTimer();
}
/*
override public function removeEvents():void
{
SharedMain.geniDispatcher.removeEventListener(GeniEvent.CHANGED_SLICE, sliceChanged);
SharedMain.tasker.removeEventListener(TaskEvent.CHILD_FINISHED, updateSliceChanging);
SharedMain.tasker.removeEventListener(TaskEvent.CHILD_STARTED, updateSliceChanging);
destroyTimer();
}
*/
public function sliceChanged(e:FlackEvent):void
{
......@@ -391,7 +411,6 @@ IN THE WORK.
undoButton.toolTip += " ("+_slice.history.stateName+")";
}
redoButton.toolTip = "Redo";
if(redoButton.enabled)
redoButton.toolTip += " ("+_slice.history.states[_slice.history.backIndex+1].note+")";
......@@ -399,14 +418,22 @@ IN THE WORK.
public function updateSliversInfo():void
{
// Make sure the slivers info area has been drawn.
if(expiresLabel != null)
{
startSliceButton.enabled = _slice.slivers.AllocatedAnyResources;
refreshStatusButton.enabled = slice.slivers.AllocatedAnyResources;
if(slice.expires != null)
updateSliversExpires()
}
}
public function updateSliversExpires():void
{
// Make sure the slivers info area has been drawn.
if(expiresLabel != null)
{
if(_slice != null && slice.expires != null)
{
var hoursRemaining:uint = (_slice.EarliestExpires.time - (new Date()).time)/3600000;
if(hoursRemaining < 1)
......
......@@ -766,7 +766,7 @@ IN THE WORK.
public function userChoseImageName(newName:String):void
{
var createImageTask:CreateImageCmTask = new CreateImageCmTask(node, newName);
var createImageTask:CreateImageCmTask = new CreateImageCmTask(node, newName, diskImageGlobalCheckbox.selected);
createImageTask.forceRunNow = true;
SharedMain.tasker.add(createImageTask);
}
......@@ -960,6 +960,12 @@ IN THE WORK.
includeInLayout="{createImageButton.visible}"
label="Create image"
click="createImageButton_clickHandler(event)" />
<s:CheckBox id="diskImageGlobalCheckbox"
label="Global"
toolTip="Allow other users to use this image?"
selected="true"
visible="{createImageButton.visible}"
includeInLayout="{diskImageGlobalCheckbox.visible}" />
</s:HGroup>
<s:HGroup width="100%"
gap="2">
......
......@@ -639,8 +639,8 @@ IN THE WORK.
previewLink = null;
}
}
// see if near node, preview link
else
// see if near node and editable, preview link
else if(editable)
{
for(var i:Number = 2; i < 60; i+=2)
{
......
......@@ -56,6 +56,7 @@ IN THE WORK.
import com.flack.geni.GeniMain;
import com.flack.geni.resources.sites.GeniManager;
import com.flack.geni.resources.sites.GeniManagerCollection;
import com.flack.shared.resources.sites.ApiDetails;
import mx.collections.ArrayCollection;
......@@ -98,6 +99,7 @@ IN THE WORK.
managerItems.addElement(managerCheckbox);
}
selectAllCheckbox.selected = allWatched;
forceApiButton.selected = GeniCache.getForceAmApi();
okButton.setFocus();
}
......@@ -122,6 +124,9 @@ IN THE WORK.
// Set the cache for future reference and continue;
GeniCache.setManagersToWatch(managersToWatch);
GeniCache.setAskWhichManagersToWatch(!dontAskAgainButton.selected);
GeniCache.setForceAmApi(forceApiButton.selected);
if(forceApiButton.selected)
GeniMain.geniUniverse.managers.forceApiType(ApiDetails.API_GENIAM);
callAfter(watchedManagers);
closeWindow();
}
......@@ -150,6 +155,9 @@ IN THE WORK.
<s:Button id="okButton"
label="Continue"
click="finish()" />
<s:CheckBox id="forceApiButton"
label="Force AM API"
toolTip="Use AM API on managers that by default use other frameworks (like CM API)?" />
<s:CheckBox id="dontAskAgainButton"
label="Don't ask again" />
</components:controlBarContent>
......
......@@ -192,7 +192,11 @@ IN THE WORK.
spinner.visible = false;
spinner.stopSpin();
Alert.show("You must be logged in on the authority's website in order to automatically retrieve your SSL Cert. Visit the login page? After login, come back here and try again.", "Visit login page?", Alert.YES|Alert.NO, FlexGlobals.topLevelApplication as Sprite,
Alert.show("You must be logged in on the authority's website in order to automatically retrieve your SSL Cert."+
" Visit the login page? After login, come back here and try again.",
"Visit login page?",
Alert.YES|Alert.NO,
FlexGlobals.topLevelApplication as Sprite,
function handleAction(e:CloseEvent):void {
if(e.detail == Alert.YES)
NetUtil.openWebsite(NetUtil.tryGetBaseUrl(selectedAuthority.url) + loginLocation);
......@@ -315,41 +319,52 @@ IN THE WORK.
return;
}
SharedMain.user.id = useCredential.OwnerId;
if(useCredential.type == GeniCredential.TYPE_UNKNOWN)
{
dontUseCredential(
"Flack can't determine if the given file is a user or slice credential." +
" Check to make sure you are loading a valid credential.");
return;
}
SharedMain.user.id = useCredential.getIdWithType(IdnUrn.TYPE_USER);
if(SharedMain.user.id == null)
{
dontUseCredential("No user URN found. Make sure you are selecting a valid credential file, not a key/certificate file.");
dontUseCredential(
"Flack can't find the user id in the provided file.");
return;
}
var expires:Date = useCredential.Expires;
if(expires == null)
{
dontUseCredential("Could not find expire time. Make sure you are selecting a valid credential file, not a key/certificate file.");
dontUseCredential(
"Could not find expire time." +
" Make sure you are selecting a valid credential file, not a key/certificate file.");
return;
}
else if(expires < new Date())
{
dontUseCredential("The credential has expired " + DateUtil.getTimeBetween(expires, new Date()) + " ago, please select a credential which hasn't expired.");
dontUseCredential(
"The credential has expired " + DateUtil.getTimeBetween(expires, new Date()) +
" ago, please select a credential which hasn't expired.");
return;
}
// Credential is ready to be used!
if(useCredential.TargetId.type == IdnUrn.TYPE_SLICE)
if(useCredential.type == GeniCredential.TYPE_SLICE)
{
useCredentialLabel.text = "Slice credential loaded for " + useCredential.TargetId.name;
useCredential.type = GeniCredential.TYPE_SLICE;
this.useCredentialRadiobutton.selected = true;
useCredentialLabel.text = "Slice credential loaded for " + useCredential.getIdWithType(IdnUrn.TYPE_SLICE).name;
useCredentialRadiobutton.selected = true;
}
else if(useCredential.TargetId.type == IdnUrn.TYPE_USER)
else if(useCredential.type == GeniCredential.TYPE_USER)
{
useCredentialLabel.text = "User credential loaded for " + useCredential.TargetId.name;
useCredential.type = GeniCredential.TYPE_USER;
this.useCredentialRadiobutton.selected = true;
useCredentialLabel.text = "User credential loaded for " + useCredential.getIdWithType(IdnUrn.TYPE_USER).name;
useCredentialRadiobutton.selected = true;
}
else
{
dontUseCredential("Credential with Target ID '"+useCredential.TargetId.full+"' is not a slice or user");
dontUseCredential("Credential does not appear to be for a slice or user.");
return;
}
}
......@@ -367,7 +382,7 @@ IN THE WORK.
private function dontUseCredential(errorMsg:String = ""):void
{
useCredential = null;
this.useCredentialLabel.text = "";
useCredentialLabel.text = "";
if(errorMsg.length > 0)
Alert.show(errorMsg, "Error");
}
......@@ -404,7 +419,10 @@ IN THE WORK.
{
if(useCredential == null)
{
Alert.show("You haven't selected a valid credential. Either select the option to get a user credential or select a valid credential from file.", "No credential selected");
Alert.show(
"You haven't selected a valid credential." +
" Either select the option to get a user credential or select a valid credential from file.",
"No credential selected");
return;
}
......@@ -413,7 +431,7 @@ IN THE WORK.
// Add the slice if using a slice credential
if(useCredential.type == GeniCredential.TYPE_SLICE)
{
var useSlice:Slice = new Slice(useCredential.TargetId.full);
var useSlice:Slice = new Slice(useCredential.getIdWithType(IdnUrn.TYPE_SLICE).full);
useSlice.creator = GeniMain.geniUniverse.user;
useSlice.expires = useCredential.Expires;
useSlice.hrn = useSlice.id.name;
......@@ -445,7 +463,13 @@ IN THE WORK.
]]>
</fx:Script>
<s:Label text="Your private key and certificate need to be entered below." paddingLeft="4" paddingRight="4" />
<s:HGroup width="100%" verticalAlign="middle" paddingLeft="4" paddingRight="4">
<s:Label text="Your private key and certificate need to be entered below." paddingLeft="4" width="100%" />
<s:Button icon="{ImageUtil.helpIcon}"
chromeColor="#56A5EC"
label="Need help?"
click="NetUtil.openWebsite(GeniMain.tutorialLoginUrl);" />
</s:HGroup>
<s:HGroup width="100%" verticalAlign="middle" paddingLeft="4" paddingRight="4">
<components:ImageButton icon="{ImageUtil.saveIcon}"
toolTip="Save to file"
......@@ -490,7 +514,13 @@ IN THE WORK.
<s:CheckBox id="rememberUnencryptedCertCheckbox" label="Remember" visible="false" includeInLayout="{rememberUnencryptedCertCheckbox.visible}" />
</s:HGroup>
<s:HGroup id="passwordGroup" width="100%" paddingLeft="4" paddingRight="4" verticalAlign="middle" visible="false" includeInLayout="{passwordGroup.visible}">
<s:HGroup id="passwordGroup"
width="100%"
paddingLeft="4"
paddingRight="4"
verticalAlign="middle"
visible="false"
includeInLayout="{passwordGroup.visible}">
<s:Image source="{ImageUtil.keyIcon}" />
<s:TextInput id="passwordField"
width="100%"
......
......@@ -46,6 +46,7 @@ package com.flack.geni.resources.docs
public static const TYPE_USER:int = 0;
public static const TYPE_SLICE:int = 1;
public static const TYPE_SLIVER:int = 2;
public static const TYPE_UNKNOWN:int = 4;
private var _xml:XML = null;
private var _raw:String = "";
......@@ -81,7 +82,7 @@ package com.flack.geni.resources.docs
return _xml;
}
public function get OwnerId():IdnUrn
private function get OwnerId():IdnUrn
{
try
{
......@@ -94,7 +95,7 @@ package com.flack.geni.resources.docs
return null;
}
public function get TargetId():IdnUrn
private function get TargetId():IdnUrn
{
try
{
......@@ -106,6 +107,17 @@ package com.flack.geni.resources.docs
return null;
}
public function getIdWithType(specifiedType:String):IdnUrn
{
var ownerId:IdnUrn = OwnerId;
if(ownerId != null && ownerId.type == specifiedType)
return ownerId;
var targetId:IdnUrn = TargetId;
if(targetId != null && targetId.type == specifiedType)
return targetId;
return null;
}
public function get Expires():Date
{
try
......@@ -131,6 +143,29 @@ package com.flack.geni.resources.docs
* What type of object is this a credential for?
*/
public var type:int;
public var version:GeniCredentialVersion;
/**
*
* @return Detected type if understandable by Flack.
*
*/
public function get GuessedType():int
{
var ownerId:IdnUrn = OwnerId;
var targetId:IdnUrn = TargetId;
if(targetId != null) {
if(targetId.type == IdnUrn.TYPE_SLIVER || ownerId.type == IdnUrn.TYPE_SLIVER)
return TYPE_SLIVER;
if(targetId.type == IdnUrn.TYPE_SLICE || ownerId.type == IdnUrn.TYPE_SLICE)
return TYPE_SLICE;
if(targetId.type == IdnUrn.TYPE_USER || ownerId.type == IdnUrn.TYPE_USER)
return TYPE_USER;
}
return TYPE_UNKNOWN;
}
/**
* What gave us this credential?
*/
......@@ -144,12 +179,20 @@ package com.flack.geni.resources.docs
*
*/
public function GeniCredential(stringRepresentation:String = "",
newType:int = TYPE_USER,
newSource:IdentifiableObject = null)
newType:int = TYPE_UNKNOWN,
newSource:IdentifiableObject = null,
newVersion:GeniCredentialVersion = null)
{
Raw = stringRepresentation;
type = newType;
source = newSource;
version = newVersion;
if(version == null)
version = GeniCredentialVersion.Default;
// Set the type if we understand this credential.
type = newType;
if(stringRepresentation.length > 0 && type == TYPE_UNKNOWN)
type = GuessedType;
}
}
}
\ No newline at end of file
/* GENIPUBLIC-COPYRIGHT
* Copyright (c) 2008-2012 University of Utah and the Flux Group.
* All rights reserved.
*
* Permission to use, copy, modify and distribute this software is hereby
* granted provided that (1) source code retains these copyright, permission,
* and disclaimer notices, and (2) redistributions including binaries
* reproduce the notices in supporting documentation.
*
* THE UNIVERSITY OF UTAH ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. THE UNIVERSITY OF UTAH DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*/
package com.flack.geni.resources.docs
{
/**
* Type information about a credential format
*
* @author mstrum
*
*/
public class GeniCredentialVersion
{
// Types
public static const TYPE_SFA:String = "geni_sfa";
public static const TYPE_ABAC:String = "geni_abac";
public static const TYPE_UNKNOWN:String = "";
public static function typeToShort(type:String):String
{
switch(type)
{
case TYPE_SFA: return"SFA";
case TYPE_ABAC: return "ABAC";
case TYPE_UNKNOWN: return "Unknown";
default:
return "??";
}
}
public static function get Default():GeniCredentialVersion
{
return new GeniCredentialVersion(TYPE_SFA, 2);
}
/**
* What type is the credential? (SFA, ABAC, etc.)
*/
public var type:String;
[Bindable]
public var version:Number;
/**
*
* @return Very short string representation (eg. PGv2)
*
*/
public function get ShortString():String
{
return GeniCredentialVersion.typeToShort(type) + "v" + version.toString();
}
/**
*
* @param newType Type of credential
* @param newVersion Credential version
*
*/
public function GeniCredentialVersion(newType:String,
newVersion:Number = NaN)
{
type = newType;
version = newVersion;
}
public function toString():String
{
return "[GeniCredentialVersion Type="+type+", Version="+version+"]";
}
}
}
\ No newline at end of file
/* GENIPUBLIC-COPYRIGHT
* Copyright (c) 2008-2012 University of Utah and the Flux Group.
* All rights reserved.
*
* Permission to use, copy, modify and distribute this software is hereby
* granted provided that (1) source code retains these copyright, permission,
* and disclaimer notices, and (2) redistributions including binaries
* reproduce the notices in supporting documentation.
*
* THE UNIVERSITY OF UTAH ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. THE UNIVERSITY OF UTAH DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*/
package com.flack.geni.resources.docs
{
/**
* List of RSPEC versions
*
* @author mstrum
*
*/
public final class GeniCredentialVersionCollection
{
public var collection:Vector.<GeniCredentialVersion> = new Vector.<GeniCredentialVersion>();
public function GeniCredentialVersionCollection(src:Array = null)
{
collection = new Vector.<GeniCredentialVersion>();
if(src != null)
{
for each(var old:GeniCredentialVersion in src)
collection.push(old);