Thomas Vachuska

Removed warden; moved to separate repo.

Change-Id: I76ae777891ad3256f1bb30f11c17c0aebfc1ed5d
1 -#!/bin/bash
2 -# Creates a cell definition from the given name and LXC info
3 -
4 -name="$1"
5 -apps="${2:-drivers,openflow,proxyarp,mobility,pathpainter}"
6 -
7 -echo "export ONOS_CELL=borrow"
8 -echo "export ONOS_NIC=\"10.128.11.*\""
9 -
10 -sudo lxc-ls -F "name,ipv4" --fancy | grep $name | \
11 - sed "s/^$name-/OC/" | tr "[:lower:]" "[:upper:]" | \
12 - sed -r 's/[ ]+/\=/;s/^/export /'
13 -
14 -echo "export OCT=\"10.128.11.1\""
15 -echo "export ONOS_USER=sdn"
16 -echo "export ONOS_USE_SSH=true"
17 -echo "export ONOS_APPS=${apps}"
18 -echo "export ONOS_WEB_USER=onos"
19 -echo "export ONOS_WEB_PASS=rocks"
1 -#!/bin/bash
2 -# Creates a new node from the base image.
3 -
4 -base="$1"
5 -ip="$2"
6 -name="$3"
7 -shift 3
8 -key="$@"
9 -
10 -sudo lxc-clone -o $base -n $name
11 -
12 -sudo chmod 777 /var/lib/lxc
13 -sudo chmod 777 /var/lib/lxc/$name
14 -sudo chmod 666 /var/lib/lxc/$name/config
15 -
16 -sudo cat >>/var/lib/lxc/$name/config <<EOF
17 -lxc.network.ipv4 = ${ip}/16
18 -lxc.network.ipv4.gateway = 10.128.0.1
19 -EOF
20 -
21 -sudo chmod 644 /var/lib/lxc/$name/config
22 -sudo chmod 750 /var/lib/lxc/$name
23 -sudo chmod 700 /var/lib/lxc
24 -
25 -sudo lxc-start -d -n $name
26 -sudo lxc-attach -n $name -- ping -c1 8.8.8.8
27 -sudo lxc-attach -n $name -- bash -c "echo $key >> /home/sdn/.ssh/authorized_keys"
28 -sudo lxc-attach -n $name -- bash -c "sed -i \"s/127.0.1.1.*/127.0.1.1 $name/\" /etc/hosts"
1 -#!/bin/bash
2 -# Creates a new cell.
3 -
4 -name="$1"
5 -ipx="$2"
6 -spec="$3"
7 -shift 3
8 -key="$@"
9 -
10 -cd $(dirname $0)
11 -
12 -nodes=${spec%+*}
13 -mininet=${spec#*+}
14 -
15 -sudo lxc-attach -n bit-proxy -- bash -c "grep -qF \"$key\" /home/sdn/.ssh/authorized_keys || echo $key >> /home/sdn/.ssh/authorized_keys"
16 -
17 -if [ $mininet -ge 1 ]; then
18 - ./clone-node base-mininet ${ipx/x/0} $name-n "$key"
19 -fi
20 -
21 -let n=1
22 -while [ $n -le $nodes ]; do
23 - ./clone-node base-onos ${ipx/x/$n} $name-$n "$key"
24 - let n=n+1
25 -done
1 -#!/bin/bash
2 -# Destroys an LXC cell with the specified name.
3 -
4 -name=$1
5 -spec=$2
6 -
7 -nodes=${spec%+*}
8 -mininet=${spec#*+}
9 -
10 -cd $(dirname $0)
11 -
12 -if [ $mininet -ge 1 ]; then
13 - ./destroy-node $name-n
14 -fi
15 -
16 -let n=1
17 -while [ $n -le $nodes ]; do
18 - ./destroy-node $name-$n
19 - let n=n+1
20 -done
1 -#!/bin/bash
2 -# Destroys an LXC node with the specified name.
3 -
4 -name=$1
5 -[ "$name" = "onos-base" ] && echo "Don't do that!" && exit 1
6 -[ "$name" = "mininet-base" ] && echo "Don't do that!" && exit 1
7 -
8 -sudo lxc-stop -n $name
9 -sudo lxc-destroy -n $name
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2015-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<project xmlns="http://maven.apache.org/POM/4.0.0"
18 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
20 - <modelVersion>4.0.0</modelVersion>
21 -
22 - <parent>
23 - <groupId>org.onosproject</groupId>
24 - <artifactId>onlab-utils</artifactId>
25 - <version>1.6.0-SNAPSHOT</version>
26 - <relativePath>../pom.xml</relativePath>
27 - </parent>
28 -
29 - <artifactId>onlab-warden</artifactId>
30 - <packaging>jar</packaging>
31 -
32 - <description>System Test Cell Warden</description>
33 -
34 - <dependencies>
35 - <dependency>
36 - <groupId>org.eclipse.jetty</groupId>
37 - <artifactId>jetty-server</artifactId>
38 - <version>8.1.18.v20150929</version>
39 - </dependency>
40 - <dependency>
41 - <groupId>org.eclipse.jetty</groupId>
42 - <artifactId>jetty-servlet</artifactId>
43 - <version>8.1.18.v20150929</version>
44 - </dependency>
45 - <dependency>
46 - <groupId>junit</groupId>
47 - <artifactId>junit</artifactId>
48 - <version>4.12</version>
49 - <scope>test</scope>
50 - </dependency>
51 - <dependency>
52 - <groupId>org.onosproject</groupId>
53 - <artifactId>onlab-misc</artifactId>
54 - <version>${project.version}</version>
55 - <scope>test</scope>
56 - </dependency>
57 - <dependency>
58 - <groupId>org.onosproject</groupId>
59 - <artifactId>onlab-junit</artifactId>
60 - <scope>test</scope>
61 - </dependency>
62 - </dependencies>
63 -
64 - <build>
65 - <plugins>
66 - <plugin>
67 - <groupId>org.apache.maven.plugins</groupId>
68 - <artifactId>maven-shade-plugin</artifactId>
69 - <version>2.4.3</version>
70 - <configuration>
71 - <transformers>
72 - <transformer
73 - implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
74 - <mainClass>org.onlab.warden.Main</mainClass>
75 - </transformer>
76 - </transformers>
77 - <filters>
78 - <filter>
79 - <artifact>*:*</artifact>
80 - <excludes>
81 - <exclude>META-INF/*.SF</exclude>
82 - <exclude>META-INF/*.DSA</exclude>
83 - <exclude>META-INF/*.RSA</exclude>
84 - </excludes>
85 - </filter>
86 - </filters>
87 - </configuration>
88 - <executions>
89 - <execution>
90 - <phase>package</phase>
91 - <goals>
92 - <goal>shade</goal>
93 - </goals>
94 - </execution>
95 - </executions>
96 - </plugin>
97 -
98 - <plugin>
99 - <groupId>org.apache.maven.plugins</groupId>
100 - <artifactId>maven-surefire-plugin</artifactId>
101 - </plugin>
102 - </plugins>
103 - </build>
104 -
105 -</project>
1 -/*
2 - * Copyright 2016 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onlab.warden;
18 -
19 -import org.eclipse.jetty.server.Server;
20 -import org.eclipse.jetty.servlet.ServletHandler;
21 -import org.eclipse.jetty.util.log.Logger;
22 -
23 -/**
24 - * Main program for executing scenario test warden.
25 - */
26 -public final class Main {
27 -
28 - // Public construction forbidden
29 - private Main(String[] args) {
30 - }
31 -
32 - /**
33 - * Main entry point for the cell warden.
34 - *
35 - * @param args command-line arguments
36 - */
37 - public static void main(String[] args) {
38 - Main main = new Main(args);
39 - main.run();
40 - }
41 -
42 - // Runs the warden processing
43 - private void run() {
44 - startWebServer();
45 - }
46 -
47 - // Initiates a web-server.
48 - private static void startWebServer() {
49 - WardenServlet.warden = new Warden();
50 - org.eclipse.jetty.util.log.Log.setLog(new NullLogger());
51 - Server server = new Server(4321);
52 - ServletHandler handler = new ServletHandler();
53 - server.setHandler(handler);
54 - handler.addServletWithMapping(WardenServlet.class, "/*");
55 - try {
56 - server.start();
57 - } catch (Exception e) {
58 - print("Warden already active...");
59 - }
60 - }
61 -
62 - private static void print(String s) {
63 - System.out.println(s);
64 - }
65 -
66 - // Logger to quiet Jetty down
67 - private static class NullLogger implements Logger {
68 - @Override
69 - public String getName() {
70 - return "quiet";
71 - }
72 -
73 - @Override
74 - public void warn(String msg, Object... args) {
75 - }
76 -
77 - @Override
78 - public void warn(Throwable thrown) {
79 - }
80 -
81 - @Override
82 - public void warn(String msg, Throwable thrown) {
83 - }
84 -
85 - @Override
86 - public void info(String msg, Object... args) {
87 - }
88 -
89 - @Override
90 - public void info(Throwable thrown) {
91 - }
92 -
93 - @Override
94 - public void info(String msg, Throwable thrown) {
95 - }
96 -
97 - @Override
98 - public boolean isDebugEnabled() {
99 - return false;
100 - }
101 -
102 - @Override
103 - public void setDebugEnabled(boolean enabled) {
104 - }
105 -
106 - @Override
107 - public void debug(String msg, Object... args) {
108 - }
109 -
110 - @Override
111 - public void debug(Throwable thrown) {
112 - }
113 -
114 - @Override
115 - public void debug(String msg, Throwable thrown) {
116 - }
117 -
118 - @Override
119 - public Logger getLogger(String name) {
120 - return this;
121 - }
122 -
123 - @Override
124 - public void ignore(Throwable ignored) {
125 - }
126 - }
127 -
128 -}
1 -/*
2 - * Copyright 2016 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onlab.warden;
18 -
19 -import static com.google.common.base.Preconditions.checkState;
20 -
21 -/**
22 - * Cell reservation record.
23 - */
24 -final class Reservation {
25 -
26 - final String cellName;
27 - final String userName;
28 - final long time;
29 - final int duration;
30 - final String cellSpec;
31 -
32 - // Creates a new reservation record
33 - Reservation(String cellName, String userName, long time, int duration, String cellSpec) {
34 - this.cellName = cellName;
35 - this.userName = userName;
36 - this.time = time;
37 - this.duration = duration;
38 - this.cellSpec = cellSpec;
39 - }
40 -
41 - /**
42 - * Decodes reservation record from the specified line.
43 - *
44 - * @param line string line
45 - */
46 - Reservation(String line) {
47 - String[] fields = line.trim().split("\t");
48 - checkState(fields.length == 5, "Incorrect reservation encoding");
49 - this.cellName = fields[0];
50 - this.userName = fields[1];
51 - this.time = Long.parseLong(fields[2]);
52 - this.duration = Integer.parseInt(fields[3]);
53 - this.cellSpec = fields[4];
54 - }
55 -
56 - /**
57 - * Encodes reservation record into a string line.
58 - *
59 - * @return encoded string
60 - */
61 - String encode() {
62 - return String.format("%s\t%s\t%s\t%s\t%s\n", cellName, userName, time, duration, cellSpec);
63 - }
64 -
65 -}
1 -/*
2 - * Copyright 2016 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onlab.warden;
18 -
19 -import com.google.common.collect.ImmutableSet;
20 -import com.google.common.collect.Lists;
21 -import com.google.common.collect.Maps;
22 -import com.google.common.io.ByteStreams;
23 -
24 -import java.io.File;
25 -import java.io.FileInputStream;
26 -import java.io.FileOutputStream;
27 -import java.io.IOException;
28 -import java.io.InputStream;
29 -import java.io.PrintWriter;
30 -import java.text.SimpleDateFormat;
31 -import java.util.ArrayList;
32 -import java.util.Date;
33 -import java.util.HashSet;
34 -import java.util.List;
35 -import java.util.Map;
36 -import java.util.Random;
37 -import java.util.Set;
38 -import java.util.Timer;
39 -import java.util.TimerTask;
40 -import java.util.concurrent.TimeUnit;
41 -
42 -import static com.google.common.base.Preconditions.*;
43 -
44 -/**
45 - * Warden for tracking use of shared test cells.
46 - */
47 -class Warden {
48 -
49 - private static final String CELL_NOT_NULL = "Cell name cannot be null";
50 - private static final String USER_NOT_NULL = "User name cannot be null";
51 - private static final String KEY_NOT_NULL = "User key cannot be null";
52 - private static final String UTF_8 = "UTF-8";
53 -
54 - private static final long TIMEOUT = 10; // 10 seconds
55 - private static final int MAX_MINUTES = 240; // 4 hours max
56 - private static final int MINUTE = 60_000; // 1 minute
57 - private static final int DEFAULT_MINUTES = 60;
58 -
59 - private static final String DEFAULT_SPEC = "3+1";
60 -
61 - private final File log = new File("warden.log");
62 -
63 - // Allow overriding these for unit tests.
64 - static String cmdPrefix = "";
65 - static File root = new File(".");
66 -
67 - private final File cells = new File(root, "cells");
68 - private final File supported = new File(cells, "supported");
69 - private final File reserved = new File(cells, "reserved");
70 -
71 - private final Random random = new Random();
72 -
73 - /**
74 - * Creates a new cell warden.
75 - */
76 - Warden() {
77 - reserved.mkdirs();
78 - random.setSeed(System.currentTimeMillis());
79 - Timer timer = new Timer("cell-pruner", true);
80 - timer.schedule(new Reposessor(), MINUTE / 4, MINUTE / 2);
81 - }
82 -
83 - /**
84 - * Returns list of names of supported cells.
85 - *
86 - * @return list of cell names
87 - */
88 - Set<String> getCells() {
89 - String[] list = supported.list();
90 - return list != null ? ImmutableSet.copyOf(list) : ImmutableSet.of();
91 - }
92 -
93 - /**
94 - * Returns list of names of available cells.
95 - *
96 - * @return list of cell names
97 - */
98 - Set<String> getAvailableCells() {
99 - Set<String> available = new HashSet<>(getCells());
100 - available.removeAll(getReservedCells());
101 - return ImmutableSet.copyOf(available);
102 - }
103 -
104 - /**
105 - * Returns list of names of reserved cells.
106 - *
107 - * @return list of cell names
108 - */
109 - Set<String> getReservedCells() {
110 - String[] list = reserved.list();
111 - return list != null ? ImmutableSet.copyOf(list) : ImmutableSet.of();
112 - }
113 -
114 - /**
115 - * Returns the host name on which the specified cell is hosted.
116 - *
117 - * @param cellName cell name
118 - * @return host name where the cell runs
119 - */
120 - String getCellHost(String cellName) {
121 - return getCellInfo(cellName).hostName;
122 - }
123 -
124 - /**
125 - * Returns reservation for the specified user.
126 - *
127 - * @param userName user name
128 - * @return cell reservation record or null if user does not have one
129 - */
130 - Reservation currentUserReservation(String userName) {
131 - checkNotNull(userName, USER_NOT_NULL);
132 - for (String cellName : getReservedCells()) {
133 - Reservation reservation = currentCellReservation(cellName);
134 - if (reservation != null && userName.equals(reservation.userName)) {
135 - return reservation;
136 - }
137 - }
138 - return null;
139 - }
140 -
141 - /**
142 - * Returns the name of the user who reserved the given cell.
143 - *
144 - * @param cellName cell name
145 - * @return cell reservation record or null if cell is not reserved
146 - */
147 - Reservation currentCellReservation(String cellName) {
148 - checkNotNull(cellName, CELL_NOT_NULL);
149 - File cellFile = new File(reserved, cellName);
150 - if (!cellFile.exists()) {
151 - return null;
152 - }
153 - try (InputStream stream = new FileInputStream(cellFile)) {
154 - return new Reservation(new String(ByteStreams.toByteArray(stream), "UTF-8"));
155 - } catch (IOException e) {
156 - throw new IllegalStateException("Unable to get current user for cell " + cellName, e);
157 - }
158 - }
159 -
160 - /**
161 - * Reserves a cell for the specified user and their public access key.
162 - *
163 - * @param userName user name
164 - * @param sshKey user ssh public key
165 - * @param minutes optional number of minutes for reservation
166 - * @param cellSpec optional cell specification string
167 - * @return reserved cell definition
168 - */
169 - synchronized String borrowCell(String userName, String sshKey, int minutes,
170 - String cellSpec) {
171 - checkNotNull(userName, USER_NOT_NULL);
172 - checkArgument(userName.matches("[\\w.-]+"), "Invalid user name %s", userName);
173 - checkNotNull(sshKey, KEY_NOT_NULL);
174 - checkArgument(minutes < MAX_MINUTES, "Number of minutes must be less than %d", MAX_MINUTES);
175 - checkArgument(minutes >= 0, "Number of minutes must be non-negative");
176 - checkArgument(cellSpec == null || cellSpec.matches("[\\d]+\\+[0-1]"),
177 - "Invalid cell spec string %s", cellSpec);
178 - Reservation reservation = currentUserReservation(userName);
179 - if (reservation == null) {
180 - // If there is no reservation for the user, create one
181 - String cellName = findAvailableCell();
182 - reservation = new Reservation(cellName, userName, System.currentTimeMillis(),
183 - minutes == 0 ? DEFAULT_MINUTES : minutes,
184 - cellSpec == null ? DEFAULT_SPEC : cellSpec);
185 - } else if (minutes == 0) {
186 - // If minutes are 0, simply return the cell definition
187 - return getCellDefinition(reservation.cellName);
188 - } else {
189 - // If minutes are > 0, update the existing cell reservation
190 - reservation = new Reservation(reservation.cellName, userName,
191 - System.currentTimeMillis(), minutes,
192 - reservation.cellSpec);
193 - }
194 -
195 - reserveCell(reservation);
196 - createCell(reservation, sshKey);
197 - log(userName, reservation.cellName, reservation.cellSpec,
198 - "borrowed for " + reservation.duration + " minutes");
199 - return getCellDefinition(reservation.cellName);
200 - }
201 -
202 - /**
203 - * Returns name of an available cell. Cell is chosen based on the load
204 - * of its hosting server; a random one will be chosen from the set of
205 - * cells hosted by the least loaded server.
206 - *
207 - * @return name of an available cell
208 - */
209 - private String findAvailableCell() {
210 - Set<String> cells = getAvailableCells();
211 - checkState(!cells.isEmpty(), "No cells are presently available");
212 - Map<String, ServerInfo> load = Maps.newHashMap();
213 -
214 - cells.stream().map(this::getCellInfo)
215 - .forEach(info -> load.compute(info.hostName, (k, v) -> v == null ?
216 - new ServerInfo(info.hostName) : v.bumpLoad(info)));
217 -
218 - List<ServerInfo> servers = new ArrayList<>(load.values());
219 - servers.sort((a, b) -> b.load - a.load);
220 - ServerInfo server = servers.get(0);
221 - return server.cells.get(random.nextInt(server.cells.size())).cellName;
222 - }
223 -
224 - /**
225 - * Returns the specified cell for the specified user and their public access key.
226 - *
227 - * @param userName user name
228 - */
229 - synchronized void returnCell(String userName) {
230 - checkNotNull(userName, USER_NOT_NULL);
231 - Reservation reservation = currentUserReservation(userName);
232 - checkState(reservation != null, "User %s has no cell reservations", userName);
233 -
234 - unreserveCell(reservation);
235 - destroyCell(reservation);
236 - log(userName, reservation.cellName, reservation.cellSpec, "returned");
237 - }
238 -
239 - /**
240 - * Reserves the specified cell for the user the source file and writes the
241 - * specified content to the target file.
242 - *
243 - * @param reservation cell reservation record
244 - */
245 - private void reserveCell(Reservation reservation) {
246 - File cellFile = new File(reserved, reservation.cellName);
247 - try (FileOutputStream stream = new FileOutputStream(cellFile)) {
248 - stream.write(reservation.encode().getBytes(UTF_8));
249 - } catch (IOException e) {
250 - throw new IllegalStateException("Unable to reserve cell " + reservation.cellName, e);
251 - }
252 - }
253 -
254 - /**
255 - * Returns the cell definition of the specified cell.
256 - *
257 - * @param cellName cell name
258 - * @return cell definition
259 - */
260 - private String getCellDefinition(String cellName) {
261 - CellInfo cellInfo = getCellInfo(cellName);
262 - return exec(String.format("ssh %s warden/bin/cell-def %s",
263 - cellInfo.hostName, cellInfo.cellName));
264 - }
265 -
266 - /**
267 - * Cancels the specified reservation.
268 - *
269 - * @param reservation reservation record
270 - */
271 - private void unreserveCell(Reservation reservation) {
272 - checkState(new File(reserved, reservation.cellName).delete(),
273 - "Unable to return cell %s", reservation.cellName);
274 - }
275 -
276 - /**
277 - * Creates the cell for the specified user SSH key.
278 - *
279 - * @param reservation cell reservation
280 - * @param sshKey ssh key
281 - */
282 - private void createCell(Reservation reservation, String sshKey) {
283 - CellInfo cellInfo = getCellInfo(reservation.cellName);
284 - String cmd = String.format("ssh %s warden/bin/create-cell %s %s %s %s",
285 - cellInfo.hostName, cellInfo.cellName,
286 - cellInfo.ipPrefix, reservation.cellSpec, sshKey);
287 - exec(cmd);
288 - }
289 -
290 - /**
291 - * Destroys the specified cell.
292 - *
293 - * @param reservation reservation record
294 - */
295 - private void destroyCell(Reservation reservation) {
296 - CellInfo cellInfo = getCellInfo(reservation.cellName);
297 - exec(String.format("ssh %s warden/bin/destroy-cell %s %s",
298 - cellInfo.hostName, cellInfo.cellName, reservation.cellSpec));
299 - }
300 -
301 - /**
302 - * Reads the information about the specified cell.
303 - *
304 - * @param cellName cell name
305 - * @return cell information
306 - */
307 - private CellInfo getCellInfo(String cellName) {
308 - File cellFile = new File(supported, cellName);
309 - try (InputStream stream = new FileInputStream(cellFile)) {
310 - String[] fields = new String(ByteStreams.toByteArray(stream), UTF_8).split(" ");
311 - return new CellInfo(cellName, fields[0], fields[1]);
312 - } catch (IOException e) {
313 - throw new IllegalStateException("Unable to definition for cell " + cellName, e);
314 - }
315 - }
316 -
317 - // Executes the specified command.
318 - private String exec(String command) {
319 - try {
320 - Process process = Runtime.getRuntime().exec(cmdPrefix + command);
321 - String output = new String(ByteStreams.toByteArray(process.getInputStream()), UTF_8);
322 - process.waitFor(TIMEOUT, TimeUnit.SECONDS);
323 - return process.exitValue() == 0 ? output : null;
324 - } catch (Exception e) {
325 - throw new IllegalStateException("Unable to execute " + command);
326 - }
327 - }
328 -
329 - // Creates an audit log entry.
330 - private void log(String userName, String cellName, String cellSpec, String action) {
331 - try (FileOutputStream fos = new FileOutputStream(log, true);
332 - PrintWriter pw = new PrintWriter(fos)) {
333 - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
334 - pw.println(String.format("%s\t%s\t%s-%s\t%s", format.format(new Date()),
335 - userName, cellName, cellSpec, action));
336 - pw.flush();
337 - } catch (IOException e) {
338 - throw new IllegalStateException("Unable to log reservation action", e);
339 - }
340 - }
341 -
342 - // Carrier of cell information
343 - private final class CellInfo {
344 - final String cellName;
345 - final String hostName;
346 - final String ipPrefix;
347 -
348 - private CellInfo(String cellName, String hostName, String ipPrefix) {
349 - this.cellName = cellName;
350 - this.hostName = hostName;
351 - this.ipPrefix = ipPrefix;
352 - }
353 - }
354 -
355 - // Carrier of cell server information
356 - private final class ServerInfo {
357 - final String hostName;
358 - int load = 0;
359 - List<CellInfo> cells = Lists.newArrayList();
360 -
361 - private ServerInfo(String hostName) {
362 - this.hostName = hostName;
363 - }
364 -
365 - private ServerInfo bumpLoad(CellInfo info) {
366 - cells.add(info);
367 - load++; // TODO: bump by cell size later
368 - return this;
369 - }
370 - }
371 -
372 - // Task for re-possessing overdue cells
373 - private final class Reposessor extends TimerTask {
374 - @Override
375 - public void run() {
376 - long now = System.currentTimeMillis();
377 - for (String cellName : getReservedCells()) {
378 - Reservation reservation = currentCellReservation(cellName);
379 - if (reservation != null &&
380 - (reservation.time + reservation.duration * MINUTE) < now) {
381 - try {
382 - returnCell(reservation.userName);
383 - } catch (Exception e) {
384 - e.printStackTrace();
385 - }
386 - }
387 - }
388 - }
389 - }
390 -}
1 -/*
2 - * Copyright 2016 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onlab.warden;
18 -
19 -import com.google.common.io.ByteStreams;
20 -import org.eclipse.jetty.server.Response;
21 -
22 -import javax.servlet.ServletException;
23 -import javax.servlet.http.HttpServlet;
24 -import javax.servlet.http.HttpServletRequest;
25 -import javax.servlet.http.HttpServletResponse;
26 -import java.io.IOException;
27 -import java.io.PrintWriter;
28 -import java.text.SimpleDateFormat;
29 -import java.util.ArrayList;
30 -import java.util.Date;
31 -import java.util.List;
32 -
33 -import static com.google.common.base.Strings.isNullOrEmpty;
34 -
35 -/**
36 - * Web socket servlet capable of creating web sockets for the STC monitor.
37 - */
38 -public class WardenServlet extends HttpServlet {
39 -
40 - static Warden warden;
41 -
42 - private SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
43 -
44 - @Override
45 - protected void doGet(HttpServletRequest req, HttpServletResponse resp)
46 - throws ServletException, IOException {
47 - resp.setContentType("text/plain; charset=UTF-8");
48 - try (PrintWriter out = resp.getWriter()) {
49 - if (req.getPathInfo().endsWith("data")) {
50 - String userName = req.getParameter("user");
51 - if (userName != null) {
52 - printUserInfo(out, userName);
53 - } else {
54 - printAvailability(out);
55 - }
56 - } else {
57 - printAvailabilityText(out);
58 - }
59 - } catch (Exception e) {
60 - resp.setStatus(Response.SC_INTERNAL_SERVER_ERROR);
61 - e.printStackTrace();
62 - }
63 - }
64 -
65 - private void printUserInfo(PrintWriter out, String userName) {
66 - Reservation reservation = warden.currentUserReservation(userName);
67 - out.println(getCellStatus(null, reservation));
68 - }
69 -
70 - private void printAvailability(PrintWriter out) {
71 - List<String> list = new ArrayList<>(warden.getCells());
72 - list.sort(String::compareTo);
73 - for (String cellName : list) {
74 - Reservation reservation = warden.currentCellReservation(cellName);
75 - out.println(getCellStatus(cellName, reservation));
76 - }
77 - }
78 -
79 - private String getCellStatus(String cellName, Reservation reservation) {
80 - if (reservation != null) {
81 - long expiration = reservation.time + reservation.duration * 60_000;
82 - long remaining = (expiration - System.currentTimeMillis()) / 60_000;
83 - return String.format("%s,%s,%s,%s", reservation.cellName,
84 - reservation.cellSpec, reservation.userName, remaining);
85 - } else if (cellName != null) {
86 - return String.format("%s", cellName);
87 - }
88 - return null;
89 - }
90 -
91 - private void printAvailabilityText(PrintWriter out) {
92 - List<String> list = new ArrayList<>(warden.getCells());
93 - list.sort(String::compareTo);
94 - for (String cellName : list) {
95 - Reservation reservation = warden.currentCellReservation(cellName);
96 - if (reservation != null) {
97 - long expiration = reservation.time + reservation.duration * 60_000;
98 - long remaining = (expiration - System.currentTimeMillis()) / 60_000;
99 - out.println(String.format("%-14s\t%-10s\t%s\t%s\t%s mins (%s remaining)",
100 - cellName + "-" + reservation.cellSpec,
101 - reservation.userName,
102 - fmt.format(new Date(reservation.time)),
103 - fmt.format(new Date(expiration)),
104 - reservation.duration, remaining));
105 - } else {
106 - out.println(String.format("%-10s\t%-10s", cellName, "available"));
107 - }
108 - }
109 - }
110 -
111 - @Override
112 - protected void doPost(HttpServletRequest req, HttpServletResponse resp)
113 - throws ServletException, IOException {
114 - try (PrintWriter out = resp.getWriter()) {
115 - String sshKey = new String(ByteStreams.toByteArray(req.getInputStream()), "UTF-8");
116 - String userName = req.getParameter("user");
117 - String sd = req.getParameter("duration");
118 - String spec = req.getParameter("spec");
119 - int duration = isNullOrEmpty(sd) ? 0 : Integer.parseInt(sd);
120 - String cellDefinition = warden.borrowCell(userName, sshKey, duration, spec);
121 - out.println(cellDefinition);
122 - } catch (Exception e) {
123 - resp.setStatus(Response.SC_INTERNAL_SERVER_ERROR);
124 - e.printStackTrace();
125 - }
126 - }
127 -
128 - @Override
129 - protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
130 - throws ServletException, IOException {
131 - try (PrintWriter out = resp.getWriter()) {
132 - String userName = req.getParameter("user");
133 - warden.returnCell(userName);
134 - } catch (Exception e) {
135 - resp.setStatus(Response.SC_INTERNAL_SERVER_ERROR);
136 - e.printStackTrace();
137 - }
138 - }
139 -}
1 -/*
2 - * Copyright 2016 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * Cell warden to coordinate borrowing and returning test cells.
19 - */
20 -package org.onlab.warden;
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2016 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onlab.warden;
18 -
19 -import com.google.common.io.Files;
20 -import org.junit.After;
21 -import org.junit.Before;
22 -import org.junit.Test;
23 -import org.onlab.util.Tools;
24 -
25 -import java.io.File;
26 -import java.io.IOException;
27 -import java.util.Objects;
28 -
29 -import static org.junit.Assert.*;
30 -
31 -/**
32 - * Suite of tests for the cell warden.
33 - */
34 -public class WardenTest {
35 -
36 - private Warden warden;
37 - private File cells;
38 - private File supportedCells;
39 -
40 - @Before
41 - public void setUp() throws IOException {
42 - // Setup warden to be tested
43 - Warden.root = Files.createTempDir();
44 - Warden.cmdPrefix = "echo ";
45 - cells = new File(Warden.root, "cells");
46 - supportedCells = new File(cells, "supported");
47 - warden = new Warden();
48 -
49 - // Setup test cell information
50 - createCell("alpha", "foo");
51 - createCell("bravo", "foo");
52 - createCell("charlie", "foo");
53 - createCell("delta", "bar");
54 - createCell("echo", "bar");
55 - createCell("foxtrot", "bar");
56 -
57 - new File("warden.log").deleteOnExit();
58 - }
59 -
60 - private void createCell(String cellName, String hostName) throws IOException {
61 - File cellFile = new File(supportedCells, cellName);
62 - Files.createParentDirs(cellFile);
63 - Files.write((hostName + " " + cellName).getBytes(), cellFile);
64 - }
65 -
66 - @After
67 - public void tearDown() throws IOException {
68 - Tools.removeDirectory(Warden.root);
69 - }
70 -
71 - @Test
72 - public void basics() {
73 - assertEquals("incorrect number of cells", 6, warden.getCells().size());
74 - validateSizes(6, 0);
75 -
76 - String cellDefinition = warden.borrowCell("dude", "the-key", 0, null);
77 - assertTrue("incorrect definition", cellDefinition.contains("cell-def"));
78 - validateSizes(5, 1);
79 -
80 - Reservation dudeCell = warden.currentUserReservation("dude");
81 - validateCellState(dudeCell);
82 -
83 - warden.borrowCell("dolt", "a-key", 0, "4+1");
84 - Reservation doltCell = warden.currentUserReservation("dolt");
85 - validateCellState(doltCell);
86 - validateSizes(4, 2);
87 -
88 - assertFalse("cells should not be on the same host",
89 - Objects.equals(warden.getCellHost(dudeCell.cellName),
90 - warden.getCellHost(doltCell.cellName)));
91 -
92 - warden.returnCell("dude");
93 - validateSizes(5, 1);
94 -
95 - warden.borrowCell("dolt", "a-key", 30, null);
96 - validateSizes(5, 1);
97 -
98 - warden.returnCell("dolt");
99 - validateSizes(6, 0);
100 - }
101 -
102 - private void validateSizes(int available, int reserved) {
103 - assertEquals("incorrect number of available cells", available,
104 - warden.getAvailableCells().size());
105 - assertEquals("incorrect number of reserved cells", reserved,
106 - warden.getReservedCells().size());
107 - }
108 -
109 - private void validateCellState(Reservation reservation) {
110 - assertFalse("cell should not be available",
111 - warden.getAvailableCells().contains(reservation.cellName));
112 - assertTrue("cell should be reserved",
113 - warden.getReservedCells().contains(reservation.cellName));
114 - }
115 -
116 -}
...\ No newline at end of file ...\ No newline at end of file
1 -#! /bin/bash
2 -# -----------------------------------------------------------------------------
3 -# init.d script to run ON.Lab test cell warden
4 -## -----------------------------------------------------------------------------
5 -### BEGIN INIT INFO
6 -# Provides: warden
7 -# Required-Start: $network $remote_fs $syslog
8 -# Required-Stop: $network $remote_fs $syslog
9 -# Default-Start: 2 3 4 5
10 -# Default-Stop: 0 1 6
11 -# Short-Description: ON.Lab Test Cell Warden
12 -# Description: Warden is a broker for sharing test cell infrastructure among ON.Lab developers.
13 -### END INIT INFO
14 -
15 -WARDEN_USER="sdn"
16 -WARDEN_HOME="/home/$WARDEN_USER/warden"
17 -WARDEN_VERSION="1.6.0-SNAPSHOT"
18 -DEBUG="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
19 -
20 -cd $WARDEN_HOME
21 -
22 -start () {
23 - # Start warden if it's not already running
24 - if ! status >/dev/null; then
25 - echo "Starting Warden"
26 - startwarden
27 - else
28 - echo "Warden is already running"
29 - fi
30 -}
31 -
32 -startwarden () {
33 - start-stop-daemon --signal INT --start --chuid $WARDEN_USER \
34 - --pidfile $WARDEN_HOME/warden.pid --make-pidfile \
35 - --background --chdir $WARDEN_HOME \
36 - --exec /usr/bin/java -- -jar onlab-warden-$WARDEN_VERSION.jar \
37 - &>$WARDEN_HOME/std.log
38 -}
39 -
40 -stop () {
41 - if status >/dev/null; then
42 - echo "Stopping Warden"
43 - start-stop-daemon --signal INT --stop --chuid $WARDEN_USER \
44 - --pidfile $WARDEN_HOME/warden.pid
45 - rm warden.pid
46 - else
47 - echo "Warden is not running"
48 - fi
49 -}
50 -
51 -restart () {
52 - stop
53 - start
54 -}
55 -
56 -status () {
57 - start-stop-daemon --signal INT --status --chuid $WARDEN_USER \
58 - --pidfile $WARDEN_HOME/warden.pid
59 -}
60 -
61 -case $1 in
62 - start)
63 - start
64 - ;;
65 - stop | force-stop)
66 - stop
67 - ;;
68 - restart)
69 - shift
70 - restart "$@"
71 - ;;
72 - status)
73 - status && echo "Warden is running" || echo "Warden is stopped"
74 - exit $?
75 - ;;
76 - *)
77 - echo "Usage: $0 {start|stop|restart|status}" >&2
78 - exit 1
79 - ;;
80 -esac
81 -
82 -exit 0