Thomas Vachuska
Committed by Gerrit Code Review

Modified warden to create borrowed cells on-demand and to scrap returned ones.

Change-Id: If32a0da18ff9d4c05645017e5cc7481bbd1ab0cd
......@@ -113,17 +113,16 @@ function cell {
case "$cell" in
"borrow")
aux="/tmp/cell-$$"
curl -sS -X POST "http://$CELL_WARDEN:4321/?user=$(id -un)&duration=${2:-0}" \
curl -sS -X POST "http://$CELL_WARDEN:4321/?duration=${2:-0}&user=${3:-$(id -un)}" \
-d "$(cat ~/.ssh/id_rsa.pub)" > $aux
. $aux
rm -f $aux
export ONOS_INSTANCES=$(env | grep 'OC[0-9]*=' | sort | cut -d= -f2)
setPrimaryInstance 1 >/dev/null
cell
onos-verify-cell
;;
"return")
curl -sS -X DELETE "http://$CELL_WARDEN:4321/?user=$(id -un)"
curl -sS -X DELETE "http://$CELL_WARDEN:4321/?user=${2:-$(id -un)}"
unset ONOS_CELL ONOS_NIC ONOS_IP ONOS_APPS ONOS_BOOT_FEATURES
unset OCI OCN OCT ONOS_INSTANCES ONOS_FEATURES
unset $(env | sed -n 's:\(^OC[0-9]\{1,\}\)=.*:\1 :g p')
......
......@@ -6,6 +6,6 @@
[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
. $ONOS_ROOT/tools/build/envDefaults
for node in $(env | sort | egrep "OC[0-9N]+" | cut -d= -f2); do
printf "%s: " $node; ssh -n -o PasswordAuthentication=no $ONOS_USER@$node date
for node in $OCN $(env | sort | egrep "OC[0-9]+" | cut -d= -f2); do
printf "%s: " $node; ssh -n -o StrictHostKeyChecking=no -o PasswordAuthentication=no $ONOS_USER@$node hostname
done
......
......@@ -8,7 +8,7 @@ echo "export ONOS_CELL=borrow"
echo "export ONOS_NIC=\"10.128.11.*\""
sudo lxc-ls -F "name,ipv4" --fancy | grep $name | \
sed "s/^$name/OC/" | tr "[:lower:]" "[:upper:]" | \
sed "s/^$name-/OC/" | tr "[:lower:]" "[:upper:]" | \
sed -r 's/[ ]+/\=/;s/^/export /'
echo "export OCT=\"\$OC1\""
......
......@@ -4,7 +4,8 @@
base="$1"
ip="$2"
name="$3"
key="$4"
shift 3
key="$@"
sudo lxc-clone -o $base -n $name
......
......@@ -3,11 +3,12 @@
name="$1"
ipx="$2"
key="$3"
shift 2
key="$@"
cd $(dirname $0)
./clone-node base-mininet ${ipx/x/0} $name-mn "$key"
./clone-node base-mininet ${ipx/x/0} $name-n "$key"
for n in {1..3}; do
./clone-node base-onos ${ipx/x/$n} $name-$n "$key"
......
......@@ -5,7 +5,7 @@ name=$1
cd $(dirname $0)
./destroy-node $name-mn
./destroy-node $name-n
for n in {1..3}; do
./destroy-node $name-$n
......
......@@ -29,14 +29,11 @@ import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.google.common.base.Preconditions.*;
......@@ -106,7 +103,6 @@ class Warden {
return list != null ? ImmutableSet.copyOf(list) : ImmutableSet.of();
}
/**
* Returns reservation for the specified user.
*
......@@ -170,40 +166,76 @@ class Warden {
reservation = new Reservation(reservation.cellName, userName, now, minutes);
}
reserveCell(reservation.cellName, reservation);
installUserKeys(reservation.cellName, userName, sshKey);
reserveCell(reservation);
createCell(reservation, sshKey);
log(userName, reservation.cellName, "borrowed for " + reservation.duration + " minutes");
return getCellDefinition(reservation.cellName);
}
/**
* Returns the specified cell for the specified user and their public access key.
*
* @param userName user name
*/
synchronized void returnCell(String userName) {
checkNotNull(userName, USER_NOT_NULL);
Reservation reservation = currentUserReservation(userName);
checkState(reservation != null, "User %s has no cell reservations", userName);
unreserveCell(reservation);
destroyCell(reservation);
log(userName, reservation.cellName, "returned");
}
/**
* Reserves the specified cell for the user the source file and writes the
* specified content to the target file.
*
* @param cellName cell name
* @param reservation cell reservation record
*/
private void reserveCell(String cellName, Reservation reservation) {
try (FileOutputStream stream = new FileOutputStream(new File(reserved, cellName))) {
private void reserveCell(Reservation reservation) {
File cellFile = new File(reserved, reservation.cellName);
try (FileOutputStream stream = new FileOutputStream(cellFile)) {
stream.write(reservation.encode().getBytes(UTF_8));
} catch (IOException e) {
throw new IllegalStateException("Unable to reserve cell " + cellName, e);
throw new IllegalStateException("Unable to reserve cell " + reservation.cellName, e);
}
}
private String getCellDefinition(String cellName) {
return exec("bin/cell-def " + cellName);
}
/**
* Returns the specified cell for the specified user and their public access key.
* Cancels the specified reservation.
*
* @param userName user name
* @param reservation reservation record
*/
synchronized void returnCell(String userName) {
checkNotNull(userName, USER_NOT_NULL);
Reservation reservation = currentUserReservation(userName);
checkState(reservation != null, "User %s has no cell reservations", userName);
private void unreserveCell(Reservation reservation) {
checkState(new File(reserved, reservation.cellName).delete(),
"Unable to return cell %s", reservation.cellName);
uninstallUserKeys(reservation.cellName);
log(userName, reservation.cellName, "returned");
}
/**
* Creates the cell for the specified user SSH key.
*
* @param reservation cell reservation
* @param sshKey ssh key
*/
private void createCell(Reservation reservation, String sshKey) {
String cellInfo = getCellInfo(reservation.cellName);
String cmd = String.format("bin/create-cell %s %s %s",
reservation.cellName, cellInfo, sshKey);
exec(cmd);
}
/**
* Destroys the specified cell.
*
* @param reservation reservation record
*/
private void destroyCell(Reservation reservation) {
exec("bin/destroy-cell " + reservation.cellName);
}
/**
......@@ -212,7 +244,7 @@ class Warden {
* @param cellName cell name
* @return cell definition
*/
String getCellDefinition(String cellName) {
String getCellInfo(String cellName) {
File cellFile = new File(supported, cellName);
try (InputStream stream = new FileInputStream(cellFile)) {
return new String(ByteStreams.toByteArray(stream), UTF_8);
......@@ -221,63 +253,15 @@ class Warden {
}
}
// Returns list of cell hosts, i.e. OC#, OCN
private List<String> cellHosts(String cellName) {
ImmutableList.Builder<String> builder = ImmutableList.builder();
Pattern pattern = Pattern.compile("export OC[0-9N]=(.*)");
for (String line : getCellDefinition(cellName).split("\n")) {
Matcher matcher = pattern.matcher(line);
if (matcher.matches()) {
builder.add(matcher.group(1).replaceAll("[\"']", ""));
}
}
return builder.build();
}
// Installs the specified user's key on all hosts of the given cell.
private void installUserKeys(String cellName, String userName, String sshKey) {
File authKeysFile = authKeys(sshKey);
for (String host : cellHosts(cellName)) {
installAuthorizedKey(host, authKeysFile.getPath());
}
checkState(authKeysFile.delete(), "Unable to install user keys");
}
// Uninstalls the user keys on the specified cell
private void uninstallUserKeys(String cellName) {
for (String host : cellHosts(cellName)) {
installAuthorizedKey(host, AUTHORIZED_KEYS);
}
}
// Installs the authorized keys on the specified host.
private void installAuthorizedKey(String host, String authorizedKeysFile) {
String cmd = "scp " + authorizedKeysFile + " sdn@" + host + ":.ssh/authorized_keys";
// Executes the specified command.
private String exec(String command) {
try {
Process process = Runtime.getRuntime().exec(cmd);
Process process = Runtime.getRuntime().exec(command);
String output = new String(ByteStreams.toByteArray(process.getInputStream()), UTF_8);
process.waitFor(TIMEOUT, TimeUnit.SECONDS);
return process.exitValue() == 0 ? output : null;
} catch (Exception e) {
throw new IllegalStateException("Unable to set authorized keys for host " + host);
}
}
// Returns the file containing authorized keys that incudes the specified key.
private File authKeys(String sshKey) {
File keysFile = new File(AUTHORIZED_KEYS);
try {
File tmp = File.createTempFile("warden-", ".auth");
tmp.deleteOnExit();
try (InputStream stream = new FileInputStream(keysFile);
PrintWriter output = new PrintWriter(tmp)) {
String baseKeys = new String(ByteStreams.toByteArray(stream), UTF_8);
output.println(baseKeys);
output.println(sshKey);
return tmp;
} catch (IOException e) {
throw new IllegalStateException("Unable to generate authorized keys", e);
}
} catch (IOException e) {
throw new IllegalStateException("Unable to generate authorized keys", e);
throw new IllegalStateException("Unable to execute " + command);
}
}
......