Modified warden to create borrowed cells on-demand and to scrap returned ones.
Change-Id: If32a0da18ff9d4c05645017e5cc7481bbd1ab0cd
diff --git a/utils/warden/src/main/java/org/onlab/warden/Warden.java b/utils/warden/src/main/java/org/onlab/warden/Warden.java
index 6f6ada5..f6c091a 100644
--- a/utils/warden/src/main/java/org/onlab/warden/Warden.java
+++ b/utils/warden/src/main/java/org/onlab/warden/Warden.java
@@ -29,14 +29,11 @@
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 @@
return list != null ? ImmutableSet.copyOf(list) : ImmutableSet.of();
}
-
/**
* Returns reservation for the specified user.
*
@@ -170,28 +166,13 @@
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);
}
/**
- * 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))) {
- stream.write(reservation.encode().getBytes(UTF_8));
- } catch (IOException e) {
- throw new IllegalStateException("Unable to reserve cell " + cellName, e);
- }
- }
-
- /**
* Returns the specified cell for the specified user and their public access key.
*
* @param userName user name
@@ -200,10 +181,61 @@
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 reservation cell reservation record
+ */
+ 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 " + reservation.cellName, e);
+ }
+ }
+
+ private String getCellDefinition(String cellName) {
+ return exec("bin/cell-def " + cellName);
+ }
+
+ /**
+ * Cancels the specified reservation.
+ *
+ * @param reservation reservation record
+ */
+ 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 @@
* @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 @@
}
}
- // 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);
}
}