--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Huawei, Inc and others. All rights reserved.
+This program and the accompanying materials are made available under the
+terms of the Eclipse Public License v1.0 which accompanies this distribution,
+and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.opendaylight.nemo</groupId>
+ <artifactId>nemo.project</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.opendaylight.nemo</groupId>
+ <artifactId>nemo-tools</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <modules>
+ <module>sandbox</module>
+ </modules>
+
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/nemo.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/nemo.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/NEMO:Main</url>
+ <tag>HEAD</tag>
+ </scm>
+</project>
\ No newline at end of file
--- /dev/null
+mvn clean install -DskipTests
+mvn dependency:copy-dependencies -DstripVersion -DskipTests
\ No newline at end of file
--- /dev/null
+#switch:TYPE,NAME,DATA-PATH-ID
+#host:TYPE,NAME,UUID,Inde:IPV4,...
+#Link:TYPE,leftName,lPortId,rightName,rPortId
+
+Switch,sw1,1
+Router,sw2,2
+Firewall,firewall,1ab3cd4ef,1:192.168.1.1/16
+Link,sw1,1,sw2,1
+Link,sw1,2,firewall,1
\ No newline at end of file
--- /dev/null
+log4j.rootLogger=ERROR, stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
+
+log4j.logger.com.huawei.nemo=INFO
\ No newline at end of file
--- /dev/null
+host.name = 191.4.3.30
+host.user = root
+host.password = 123456
+controller-socket = 191.4.3.25:6633
+north.port = 10081
+config.path = /home/hj/configs
+config.hosts-file-name = host-resource.json
+config.externals-file-name = external-resource.json
+config.nodes-file-name = node-resource.json
+config.links-file-name = link-resource.json
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Huawei, Inc and others. All rights reserved.
+This program and the accompanying materials are made available under the
+terms of the Eclipse Public License v1.0 which accompanies this distribution,
+and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.opendaylight.nemo</groupId>
+ <artifactId>nemo-tools</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.opendaylight.nemo</groupId>
+ <artifactId>sandbox</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <name>${project.artifactId}</name>
+
+ <properties>
+ <log4j.version>1.7.7</log4j.version>
+ <junit.version>4.11</junit.version>
+ <jersey.version>2.11</jersey.version>
+ <enunciate.version>1.26.2</enunciate.version>
+ <cli.version>1.2</cli.version>
+ <cliche.version>1.0-SNAPSHOT</cliche.version>
+ <ssh.version>262</ssh.version>
+ <json.version>20090211</json.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${log4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-cli</groupId>
+ <artifactId>commons-cli</artifactId>
+ <version>${cli.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.googlecode.cliche</groupId>
+ <artifactId>cliche</artifactId>
+ <version>${cliche.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.ethz.ganymed</groupId>
+ <artifactId>ganymed-ssh2</artifactId>
+ <version>${ssh.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>${json.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-grizzly2-http</artifactId>
+ <version>${jersey.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-moxy</artifactId>
+ <version>${jersey.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.enunciate</groupId>
+ <artifactId>enunciate-core-annotations</artifactId>
+ <version>${enunciate.version}</version>
+ </dependency>
+ </dependencies>
+
+ <repositories>
+ <repository>
+ <id>cliche</id>
+ <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+ </repository>
+ </repositories>
+
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/nemo.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/nemo.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/NEMO:Main</url>
+ <tag>HEAD</tag>
+ </scm>
+</project>
\ No newline at end of file
--- /dev/null
+#!/bin/sh -x
+
+CONFDIR="./conf"
+parse_args() {
+ while test $# -gt 0; do
+ case "$1" in
+ "--confdir" ) shift; CONFDIR=$1 ;;
+ "-c" ) shift; CONFDIR=$1 ;;
+ esac
+ shift
+ done
+}
+
+parse_args $@
+
+# Set paths
+CTRL_HOME=`pwd`/`dirname $0`
+LAUNCHER_PATH="${CTRL_HOME}"
+LAUNCHER_MAIN="org.opendaylight.nemo.tool.sandbox.Main"
+
+# Set JVM options
+JVM_OPTS=""
+#JVM_OPTS="$JVM_OPTS -server -d64"
+#JVM_OPTS="$JVM_OPTS -Xmx2g -Xms2g -Xmn800m"
+#JVM_OPTS="$JVM_OPTS -XX:+UseParallelGC -XX:+AggressiveOpts -XX:+UseFastAccessorMethods"
+#JVM_OPTS="$JVM_OPTS -XX:MaxInlineSize=8192 -XX:FreqInlineSize=8192"
+#JVM_OPTS="$JVM_OPTS -XX:CompileThreshold=1500 -XX:PreBlockSpin=8"
+#JVM_OPTS="$JVM_OPTS -Dpython.security.respectJavaAccessibility=false"
+
+CLASSPATH="$CONFDIR:.:$LAUNCHER_PATH/target/classes:$LAUNCHER_PATH/target/dependency/*"
+java ${JVM_OPTS} -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n -cp $CLASSPATH $LAUNCHER_MAIN $@
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox;
+
+import asg.cliche.Command;
+import asg.cliche.Shell;
+import asg.cliche.ShellDependent;
+
+/**
+ * Created by hj on 12/9/15.
+ */
+public class Cli implements ShellDependent {
+ private Shell shell;
+
+ public Cli() {
+
+ }
+
+ @Override
+ public void cliSetShell(Shell shell) {
+ this.shell = shell;
+ }
+
+ @Command
+ public void install() {
+ SandBoxManager.getInstance().createNetwork();
+ }
+
+ @Command
+ public void uninstall() {
+ SandBoxManager.getInstance().destroyNetwork();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox;
+
+import ch.ethz.ssh2.Connection;
+import ch.ethz.ssh2.Session;
+import ch.ethz.ssh2.StreamGobbler;
+import org.opendaylight.nemo.tool.sandbox.utils.Config;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ * Created by hj on 12/9/15.
+ */
+public class CmdExecutor {
+ private static Connection sshConnection;
+ private static String strHostName = Config.getHostName();
+ private static String strUserName = Config.getHostUser();
+ private static String strPassword = Config.getHostPassword();
+
+ public static boolean open() {
+ try {
+ sshConnection = new Connection(strHostName);
+ sshConnection.connect();
+ if (false == sshConnection.authenticateWithPassword(strUserName, strPassword)) {
+ throw new IOException("Authentication failed!");
+ } else {
+ return true;
+ }
+ } catch (IOException objException) {
+ objException.printStackTrace();
+ if (null != sshConnection) {
+ sshConnection.close();
+ sshConnection = null;
+ }
+ }
+ return false;
+ }
+
+ public static void close() {
+ if (null != sshConnection) {
+ sshConnection.close();
+ sshConnection = null;
+ }
+ }
+
+ public static String sshExecute(String command) {
+ Session session = null;
+ try {
+ session = sshConnection.openSession();
+ if (!"root".equals(Config.getHostName())) {
+ command = "sudo " + command;
+ }
+ session.execCommand(command);
+ InputStream stdout = new StreamGobbler(session.getStdout());
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stdout));
+ String result = "";
+ while (true) {
+ String line = bufferedReader.readLine();
+ if (line != null)
+ result += "\r\n" + line;
+ else
+ break;
+ }
+ session.close();
+ return result;
+
+ } catch (IOException objException) {
+ objException.printStackTrace();
+ } finally {
+ if (null != session) {
+ session.close();
+ }
+ }
+ return null;
+ }
+
+ public static String queryInterfaceMac(String name) {
+ String result = sshExecute("ifconfig " + name);
+ return getMacFromResult(result);
+ }
+
+ public static String queryInterfaceMac(String name, String namespce) {
+ String result = sshExecute("ip netns exec " + namespce + " ifconfig " + name);
+ return getMacFromResult(result);
+ }
+
+ private static String getMacFromResult(String result) {
+ String args[] = result.split("\r\n");
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i].trim();
+ if (arg.contains("HWaddr")) {
+ String s[] = arg.split(" ");
+ return s[s.length - 1];
+ }
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox;
+
+import asg.cliche.Shell;
+import asg.cliche.ShellFactory;
+
+import java.io.IOException;
+
+/**
+ * Created by hj on 12/9/15.
+ */
+public class EasyCli {
+ private Shell shell;
+
+ public EasyCli(String prompt,String hint,Object handler){
+ shell = ShellFactory.createConsoleShell(prompt, hint, handler);
+ }
+
+ public void add(Object handler){
+ shell.addMainHandler(handler,"");
+ }
+
+ public void run(){
+ try {
+ shell.commandLoop();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox;
+
+import java.util.List;
+
+/**
+ * Created by hj on 12/14/15.
+ */
+public interface ISandboxManager {
+ public boolean createNetwork(List<String> commands);
+
+ public boolean createNetwork();
+
+ public boolean destroyNetwork();
+
+ public String getHosts();
+
+ public String getSwitches();
+
+ public String getLinks();
+
+ public String getExternals();
+
+ public String execute(String name, String command);
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox;
+
+import org.opendaylight.nemo.tool.sandbox.northbound.RestServer;
+import org.opendaylight.nemo.tool.sandbox.utils.PropertyLoader;
+
+/**
+ * Created by hj on 12/9/15.
+ */
+public class Main {
+ public static void main(String []args){
+ PropertyLoader.loadProperties("/sandbox.properties", "sandbox.properties does not exist.");
+ int northboundPort = Integer.parseInt(System.getProperty("north.port","10081"));
+ String socketAddress = "http://0.0.0.0:"+northboundPort+"/";
+ RestServer.start(socketAddress);
+ EasyCli easyCli = new EasyCli("sandbox","Authorized by Ip tech, Huawei",new Cli());
+ easyCli.run();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox;
+
+import org.json.JSONObject;
+import org.opendaylight.nemo.tool.sandbox.models.*;
+import org.opendaylight.nemo.tool.sandbox.utils.PropertyLoader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by hj on 12/9/15.
+ */
+public class SandBoxManager implements ISandboxManager {
+ private static Logger log = LoggerFactory.getLogger(SandBoxManager.class);
+ private static SandBoxManager sandBoxManager = new SandBoxManager();
+
+ public static SandBoxManager getInstance() {
+ return sandBoxManager;
+ }
+
+ private Network network = null;
+
+ private SandBoxManager() {
+ List<String> list = PropertyLoader.readLines("/Network", "Network file does not exist.");
+ network = generateNetwork(list);
+ }
+
+ @Override
+ public boolean createNetwork(List<String> list) {
+ if (CmdExecutor.open()) {
+ if (network != null && CmdExecutor.open()) {
+ network.uninstall();
+ CmdExecutor.close();
+ }
+ network = generateNetwork(list);
+ return createNetwork();
+ } else {
+ System.out.println("Can not open ssh.");
+ }
+ return false;
+
+ }
+
+ @Override
+ public boolean createNetwork() {
+ if (network != null && CmdExecutor.open()) {
+ network.install();
+ network.echoConfig();
+ CmdExecutor.close();
+ System.out.println("Network have been installed.");
+ return true;
+ } else {
+ System.out.println("Network is null or can not open ssh,Network: " + network);
+ }
+ return false;
+ }
+
+ @Override
+ public String getHosts() {
+ if (network != null && CmdExecutor.open()) {
+ JSONObject jsonObject = network.hostJsonNode();
+ CmdExecutor.close();
+ if (jsonObject != null) {
+ return jsonObject.toString();
+ }
+ } else {
+ System.out.println("Network is null or can not open ssh,Network: " + network);
+ }
+ return null;
+ }
+
+ @Override
+ public String getExternals() {
+ if (network != null && CmdExecutor.open()) {
+ JSONObject jsonObject = network.externalJsonNode();
+ CmdExecutor.close();
+ if (jsonObject != null) {
+ return jsonObject.toString();
+ }
+ } else {
+ System.out.println("Network is null or can not open ssh,Network: " + network);
+ }
+ return null;
+ }
+
+ @Override
+ public String getSwitches() {
+ if (network != null) {
+ JSONObject jsonObject = network.nodeJsonNode();
+ if (jsonObject != null) {
+ return jsonObject.toString();
+ }
+ } else {
+ System.out.println("Network is null.");
+ }
+ return null;
+ }
+
+ @Override
+ public String getLinks() {
+ if (network != null) {
+ JSONObject jsonObject = network.innerLinkJsonNode();
+ if (jsonObject != null) {
+ return jsonObject.toString();
+ }
+ } else {
+ System.out.println("Network is null.");
+ }
+ return null;
+ }
+
+ @Override
+ public boolean destroyNetwork() {
+ if (network != null && CmdExecutor.open()) {
+ network.uninstall();
+ network = null;
+ CmdExecutor.close();
+ }
+ return true;
+ }
+
+ @Override
+ public String execute(String name, String command) {
+ return network.execute(name,command);
+ }
+
+ private Network generateNetwork(List<String> list) {
+ Network network = new Network();
+ Map<String/*node name*/, List<Connector>> connectorMap = new HashMap<String, List<Connector>>();
+ List<String> nodes = new ArrayList<String>();
+ for (String line : list) {
+ if (line.startsWith("Link")) {
+ Link link = handleLink(line);
+ if (link != null) {
+ network.addLink(link);
+ saveConnector(link.getSrcConnector(), connectorMap);
+ saveConnector(link.getDstConnector(), connectorMap);
+ }
+ } else {
+ nodes.add(line);
+ }
+ }
+ for (String line : nodes) {
+ NodeType nodeType = getNodeType(line);
+ switch (nodeType) {
+ case SWITCH:
+ case ROUTER:
+ Switch aSwitch = handleSwitch(line, connectorMap);
+ if (aSwitch != null) {
+ network.addSwitch(aSwitch);
+ }
+ break;
+ case VM:
+ VirtualMachine virtualMachine = handleVirtualMachine(line, connectorMap);
+ if (virtualMachine != null) {
+ network.addHost(virtualMachine);
+ }
+ break;
+ case CACHE:
+ Cache cache = handleCache(line, connectorMap);
+ if (cache != null) {
+ network.addHost(cache);
+ }
+ break;
+ case FIREWALL:
+ Firewall firewall = handleFirewall(line, connectorMap);
+ if (firewall != null) {
+ network.addHost(firewall);
+ }
+ break;
+ default:
+ log.warn("Ignore line : {}.", line);
+ }
+ }
+ return network;
+ }
+
+ private Switch handleSwitch(String line, Map<String, List<Connector>> connectorMap) {
+ line = line.trim();
+ String args[] = line.split(",");
+ if (args.length == 3) {
+ Switch sw = null;
+ if (line.startsWith("Router"))
+ sw = new Router(args[1].trim(), Long.parseLong(args[2]));
+ else
+ sw = new Switch(args[1].trim(), Long.parseLong(args[2]));
+ List<Connector> connectors = connectorMap.get(sw.getName());
+ if (connectors != null) {
+ for (Connector connector : connectors) {
+ sw.addConnectors(connector);
+ }
+ }
+ return sw;
+ }
+ return null;
+ }
+
+ private VirtualMachine handleVirtualMachine(String line, Map<String, List<Connector>> connectorMap) {
+ line = line.trim();
+ String args[] = line.split(",");
+ if (args.length >= 4) {
+ VirtualMachine virtualMachine = new VirtualMachine(args[1].trim(),args[2].trim());
+ parserHost(args, connectorMap, virtualMachine);
+ return virtualMachine;
+ }
+ return null;
+ }
+
+ private Cache handleCache(String line, Map<String, List<Connector>> connectorMap) {
+ line = line.trim();
+ String args[] = line.split(",");
+ if (args.length >= 4) {
+ Cache cache = new Cache(args[1].trim(),args[2].trim());
+ parserHost(args, connectorMap, cache);
+ return cache;
+ }
+ return null;
+ }
+
+ private Firewall handleFirewall(String line, Map<String, List<Connector>> connectorMap) {
+ line = line.trim();
+ String args[] = line.split(",");
+ if (args.length >= 4) {
+ Firewall firewall = new Firewall(args[1].trim(),args[2].trim());
+ parserHost(args, connectorMap, firewall);
+ return firewall;
+ }
+ return null;
+ }
+
+ private void parserHost(String[] args, Map<String, List<Connector>> connectorMap, Host host) {
+ List<Connector> connectors = connectorMap.get(host.getName());
+ if (connectors != null) {
+ for (Connector connector : connectors) {
+ host.addConnectors(connector);
+ }
+ }
+ for (int i = 3; i < args.length; i++) {
+ String[] array = args[i].trim().split(":");
+ if (array.length == 2) {
+ int order = Integer.parseInt(array[0]);
+ host.putConnectorIpv4(order, array[1]);
+ }
+ }
+
+ }
+
+ private void saveConnector(Connector connector, Map<String, List<Connector>> connectorMap) {
+ String nodeName = connector.getNodeName();
+ if (!connectorMap.containsKey(nodeName)) {
+ connectorMap.put(nodeName, new ArrayList<Connector>());
+ }
+ connectorMap.get(nodeName).add(connector);
+ }
+
+ private Link handleLink(String link) {
+ link = link.trim();
+ String args[] = link.split(",");
+ if (args.length == 5) {
+ Connector lConnector = new Connector(args[1].trim(), Integer.parseInt(args[2].trim()));
+ Connector rConnector = new Connector(args[3].trim(), Integer.parseInt(args[4].trim()));
+ return new Link(lConnector, rConnector);
+ }
+ return null;
+ }
+
+ private NodeType getNodeType(String line) {
+ if (line.startsWith("Switch"))
+ return NodeType.SWITCH;
+ if (line.startsWith("Router")) {
+ return NodeType.ROUTER;
+ }
+ if (line.startsWith("Cache")) {
+ return NodeType.CACHE;
+ }
+ if (line.startsWith("Firewall")) {
+ return NodeType.FIREWALL;
+ }
+ if (line.startsWith("Vm")) {
+ return NodeType.VM;
+ }
+ return NodeType.UNKNOWN;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.models;
+
+import org.opendaylight.nemo.tool.sandbox.CmdExecutor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by hj on 12/8/15.
+ */
+public class Cache extends Host {
+ public Cache(String name,String uuId) {
+ super(NodeType.CACHE,name, uuId);
+ }
+
+ @Override
+ protected List<String> generateCommands() {
+ List<String> commands = new ArrayList<String>(generateHost());
+ //TODO: host script.
+ //open route flag
+ commands.add("ip netns exec "+getName()+"echo 1 > /proc/sys/net/ipv4/ip_forward");
+ //add default route
+ if(connectors.size()>0) {
+ commands.add("ip netns exec route add default dev "+ connectors.get(0));
+ }
+ return commands;
+ }
+
+ @Override
+ public void uninstall(){
+ try {
+ CmdExecutor.sshExecute("ip netns del " + getName());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.models;
+
+/**
+ * Created by hj on 12/8/15.
+ */
+public class Connector implements Comparable<Connector> {
+ private final int order;
+ private final String nodeName;
+
+ public Connector(String nodeName, int order) {
+ this.order = order;
+ this.nodeName = nodeName;
+ }
+
+ public String getConnectorName() {
+ return nodeName + "-" + order;
+ }
+
+ public int getOrder() {
+ return order;
+ }
+
+ public String getNodeName() {
+ return nodeName;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Connector that = (Connector) o;
+
+ if (order != that.order) return false;
+ if (nodeName != null ? !nodeName.equals(that.nodeName) : that.nodeName != null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = order;
+ result = 31 * result + (nodeName != null ? nodeName.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "SwitchInterface{" +
+ "order=" + order +
+ ", nodeName='" + nodeName + '\'' +
+ '}';
+ }
+
+ @Override
+ public int compareTo(Connector o) {
+ return order - o.order;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.models;
+
+import org.opendaylight.nemo.tool.sandbox.CmdExecutor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by hj on 12/8/15.
+ */
+public class Firewall extends Host {
+ public Firewall(String name,String uuId) {
+ super(NodeType.FIREWALL, name,uuId);
+ }
+
+ @Override
+ protected List<String> generateCommands() {
+ List<String> commands = new ArrayList<String>(generateHost());
+ //TODO: host script.
+ //open route flag
+ commands.add("ip netns exec "+getName()+"echo 1 > /proc/sys/net/ipv4/ip_forward");
+ //add default route
+ if(connectors.size()>0) {
+ commands.add("ip netns exec route add default dev "+ connectors.get(0));
+ }
+ return commands;
+ }
+
+ @Override
+ public void uninstall(){
+ try {
+ CmdExecutor.sshExecute("ip netns del " + getName());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.models;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+* Created by hj on 12/8/15.
+*/
+abstract public class Host extends Node {
+ private HashMap<Integer/*connector name*/, String/*Ipv4*/> connectorIpv4Map;
+ private final String uuid;
+
+ protected Host(NodeType nodeType, String name,String uuid) {
+ super(nodeType, name);
+ this.uuid = uuid;
+ connectorIpv4Map = new HashMap<Integer, String>();
+ }
+
+ public void putConnectorIpv4(int order, String ipv4) {
+ connectorIpv4Map.put(order, ipv4);
+ }
+
+ public String getUuid(){
+ return uuid;
+ }
+
+ public String getIpv4(int order){
+ return connectorIpv4Map.get(order);
+ }
+
+ abstract void uninstall();
+
+ protected List<String> generateHost() {
+ List<String> hostCreateCommands = new ArrayList<String>();
+ hostCreateCommands.add("ip netns add " + getName());
+ for (Connector connector : connectors) {
+ hostCreateCommands.add("ip link set " + connector.getConnectorName() + " netns " + getName());
+ }
+
+ for (Connector connector : connectors) {
+ String ipv4 = connectorIpv4Map.get(connector.getOrder());
+ if (ipv4 != null) {
+ hostCreateCommands.add("ip netns exec " + getName() + " ifconfig " + connector.getConnectorName() + " " + ipv4 + " up");
+ }
+ }
+ return hostCreateCommands;
+ }
+
+ @Override
+ public String toString() {
+ return "Host{" +
+ "name=" + getName() + '\'' +
+ "type=" + getNodeType() + '\'' +
+ "connectors='" + connectors + '\'' +
+ ", ipv4Map='" + connectorIpv4Map + '\'' +
+ '}';
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.models;
+
+import org.opendaylight.nemo.tool.sandbox.CmdExecutor;
+
+/**
+ * Created by hj on 12/8/15.
+ */
+public class Link {
+ private final Connector srcInterface;
+ private final Connector dstInterface;
+
+ public Link(Connector srcInterface, Connector dstInterface) {
+ this.srcInterface = srcInterface;
+ this.dstInterface = dstInterface;
+ }
+
+ public Connector getSrcConnector() {
+ return srcInterface;
+ }
+
+ public Connector getDstConnector() {
+ return dstInterface;
+ }
+
+ public void install() {
+ String linkAddCmd = "ip link add name " + srcInterface.getConnectorName() + " type veth peer name " + dstInterface.getConnectorName();
+ try {
+ CmdExecutor.sshExecute(linkAddCmd);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void uninstall() {
+ String linkDelCmd = "ip link del " + srcInterface.getConnectorName();
+ try {
+ CmdExecutor.sshExecute(linkDelCmd);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Link link = (Link) o;
+
+ if (dstInterface != null ? !dstInterface.equals(link.dstInterface) : link.dstInterface != null) return false;
+ if (srcInterface != null ? !srcInterface.equals(link.srcInterface) : link.srcInterface != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = srcInterface != null ? srcInterface.hashCode() : 0;
+ result = 31 * result + (dstInterface != null ? dstInterface.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Link{" +
+ "srcInterface=" + srcInterface +
+ ", dstInterface=" + dstInterface +
+ '}';
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.models;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.opendaylight.nemo.tool.sandbox.CmdExecutor;
+import org.opendaylight.nemo.tool.sandbox.utils.Config;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by hj on 12/9/15.
+ */
+public class Network {
+ private static Logger log = LoggerFactory.getLogger(Network.class);
+ private Map<String/*name*/, Host> hostMap;
+ private Map<String/*name*/, Switch> switchMap;
+ private Map<Connector/*External connector*/, Connector/*Connector on host*/> externalConnectorMap;
+ private List<Link> internalLinks;
+ private List<Link> links;
+
+ public Network() {
+ hostMap = new HashMap<String, Host>();
+ switchMap = new HashMap<String, Switch>();
+ links = new ArrayList<Link>();
+
+ externalConnectorMap = new HashMap<Connector, Connector>();
+ internalLinks = new ArrayList<Link>();
+ }
+
+ public void addHost(Host host) {
+ hostMap.put(host.getName(), host);
+ }
+
+ public void addSwitch(Switch sw) {
+ switchMap.put(sw.getName(), sw);
+ }
+
+ public void addLink(Link link) {
+ links.add(link);
+ }
+
+ public String execute(String name, String command) {
+ Host host = hostMap.get(name);
+ if (host != null) {
+ if (CmdExecutor.open()) {
+ String result = CmdExecutor.sshExecute("ip netns exec " + name + " " + command);
+ CmdExecutor.close();
+ return result;
+ } else {
+ return "Can not open ssh right now,please try again.";
+ }
+ }
+ return name + " " + "is not a firewall,can not execute " + command;
+ }
+
+ public void install() {
+ traversal();
+
+ for (Link link : links) {
+ link.install();
+ }
+
+ for (Node node : switchMap.values()) {
+ node.install();
+ }
+
+ for (Node node : hostMap.values()) {
+ node.install();
+ }
+ }
+
+ public void uninstall() {
+ for (Link link : links) {
+ link.uninstall();
+ }
+
+ pKill();
+
+ for (Host host : hostMap.values()) {
+ host.uninstall();
+ }
+ }
+
+ private void pKill() {
+ try {
+ CmdExecutor.sshExecute("pkill -9 ofdatapath");
+ CmdExecutor.sshExecute("pkill -9 ofprotocol");
+
+ CmdExecutor.sshExecute("pkill -9 fail-ofdatapath");
+ CmdExecutor.sshExecute("pkill -9 fail-ofprotocol");
+
+ CmdExecutor.sshExecute("pkill -9 ext-ofdatapath");
+ CmdExecutor.sshExecute("pkill -9 ext-ofprotocol");
+ } catch (Exception e) {
+
+ }
+ }
+
+ public void echoConfig() {
+ CmdExecutor.sshExecute("mkdir -p " + Config.getConfigPath());
+
+ String hosts = hostJsonNode().toString().replaceAll("\"", "\\\\\"").replaceAll("\\{", "\\\\{");
+ String hostsPath = Config.getConfigPath() + "/" + Config.getConfigHostsFileName();
+ CmdExecutor.sshExecute("echo " + hosts + " > " + hostsPath);
+// FileUtils.write(hostsPath, hosts);
+
+ String externals = externalJsonNode().toString().replaceAll("\"", "\\\\\"").replaceAll("\\{", "\\\\{");
+ String externalsPath = Config.getConfigPath() + "/" + Config.getConfigExternalsFileName();
+ CmdExecutor.sshExecute("echo " + externals + " > " + externalsPath);
+// FileUtils.write(externalsPath, externals);
+
+ String nodes = nodeJsonNode().toString().replaceAll("\"", "\\\\\"").replaceAll("\\{", "\\\\{");
+ String nodesPath = Config.getConfigPath() + "/" + Config.getConfigNodesFileName();
+ CmdExecutor.sshExecute("echo " + nodes + " > " + nodesPath);
+// FileUtils.write(nodesPath, nodes);
+
+ String links = externalJsonNode().toString().replaceAll("\"", "\\\\\"").replaceAll("\\{", "\\\\{");
+ String linksPath = Config.getConfigPath() + "/" + Config.getConfigLinksFileName();
+ CmdExecutor.sshExecute("echo " + links + " > " + linksPath);
+// FileUtils.write(linksPath,links);
+ }
+
+ private void traversal() {
+ externalConnectorMap.clear();
+ internalLinks.clear();
+
+ for (Link link : links) {
+ String leftNode = link.getSrcConnector().getNodeName();
+ String rightNode = link.getDstConnector().getNodeName();
+ if (hostMap.containsKey(leftNode) && switchMap.containsKey(rightNode)) {
+ externalConnectorMap.put(link.getDstConnector(), link.getSrcConnector());
+ } else if (hostMap.containsKey(rightNode) && switchMap.containsKey(leftNode)) {
+ externalConnectorMap.put(link.getSrcConnector(), link.getDstConnector());
+ } else if (switchMap.containsKey(leftNode) && switchMap.containsKey(rightNode)) {
+ internalLinks.add(link);
+ } else {
+ log.error("Illegal link: {}.", link);
+ }
+ }
+ }
+
+ public JSONObject nodeJsonNode() {
+ JSONObject root = new JSONObject();
+ JSONArray nodeArray = new JSONArray();
+ int index = 0;
+ try {
+ for (Switch sw : switchMap.values()) {
+ JSONObject nodeJson = buildNodeJson(sw);
+ if (nodeJson != null) {
+ nodeArray.put(index, nodeJson);
+ index++;
+ }
+ }
+ root.put("node", nodeArray);
+ return root;
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private JSONObject buildNodeJson(Switch sw) {
+ JSONObject nodeJson = new JSONObject();
+ try {
+ String nodeId = "openflow:" + sw.getDataPathId();
+ String type = sw instanceof Router ? "router" : "switch";
+ JSONArray attributes = defaultNodeAttributes(nodeId);
+ JSONArray ports = new JSONArray();
+ int index = 0;
+ List<Connector> connectors = sw.getConnectors();
+ for (Connector connector : connectors) {
+ JSONObject portJson = new JSONObject();
+ String portId = nodeId + ":" + connector.getOrder();
+ String portType = externalConnectorMap.containsKey(connector) ? "external" : "internal";
+ JSONArray portAttributes = defaultPortAttributes(portId);
+ portJson.put("port-id", portId);
+ portJson.put("port-type", portType);
+ portJson.put("attribute", portAttributes);
+ ports.put(index, portJson);
+ index++;
+ }
+ nodeJson.put("node-id", nodeId);
+ nodeJson.put("node-type", type);
+ nodeJson.put("attribute", attributes);
+ nodeJson.put("port", ports);
+ return nodeJson;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private JSONArray defaultNodeAttributes(String nodeId) throws JSONException {
+ JSONArray jsonArray = new JSONArray();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("name", "location");
+ jsonObject.put("value", nodeId);
+ jsonArray.put(0, jsonObject);
+ return jsonArray;
+ }
+
+ private JSONArray defaultPortAttributes(String portId) throws JSONException {
+ JSONArray jsonArray = new JSONArray();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("name", "location");
+ jsonObject.put("value", portId);
+ jsonArray.put(0, jsonObject);
+ return jsonArray;
+ }
+
+ public JSONObject externalJsonNode() {
+ JSONObject root = new JSONObject();
+ JSONArray externalMacs = new JSONArray();
+ int index = 0;
+ try {
+ for (Connector exCon : externalConnectorMap.keySet()) {
+ Connector hostCon = externalConnectorMap.get(exCon);
+ String hostMac = CmdExecutor.queryInterfaceMac(hostCon.getConnectorName(), hostCon.getNodeName());
+ Switch sw = switchMap.get(exCon.getNodeName());
+ if (hostMac != null && sw != null) {
+ JSONObject exNode = new JSONObject();
+ String nodeId = "openflow:" + sw.getDataPathId();
+ String portId = nodeId + ":" + exCon.getOrder();
+
+ exNode.put("node-id", nodeId);
+ exNode.put("port-id", portId);
+ exNode.put("mac-address", hostMac);
+ externalMacs.put(index, exNode);
+ index++;
+ }
+ }
+ root.put("external-network-mac", externalMacs);
+ return root;
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public JSONObject hostJsonNode() {
+ JSONObject root = new JSONObject();
+ JSONArray hostArray = new JSONArray();
+ int index = 0;
+ try {
+ for (Connector exCon : externalConnectorMap.keySet()) {
+ Connector hostCon = externalConnectorMap.get(exCon);
+ String exConMac = CmdExecutor.queryInterfaceMac(exCon.getConnectorName());
+ Switch sw = switchMap.get(exCon.getNodeName());
+
+ JSONObject hostJson = new JSONObject();
+ String hostName = hostCon.getNodeName();
+ Host host = hostMap.get(hostName);
+ if ( exConMac != null && sw != null && host != null) {
+ JSONArray ipv4Array = ipAddress(hostCon);
+ String nodeId = "openflow:" + sw.getDataPathId();
+ String connectorId = nodeId + ":" + exCon.getOrder();
+ hostJson.put("name", hostName);
+ hostJson.put("id", host.getUuid());
+ hostJson.put("type", host.getNodeType());
+ hostJson.put("ip-addresses", ipv4Array);
+ hostJson.put("mac-address", exConMac);
+ hostJson.put("node-id", nodeId);
+ hostJson.put("connector-id", connectorId);
+ hostArray.put(index, hostJson);
+ index++;
+ } else {
+ log.error("Can not put host [{}] to configuration file,exMac:{} sw:{} id:{}.", hostName, sw);
+ }
+ }
+ root.put("host", hostArray);
+ return root;
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private JSONArray ipAddress(Connector connector) throws JSONException {
+ JSONArray jsonArray = new JSONArray();
+ Host host = hostMap.get(connector.getNodeName());
+ if (host != null) {
+ String ipv4 = host.getIpv4(connector.getOrder());
+ if (ipv4 != null) {
+ ipv4 = ipv4 + "/";
+ ipv4 = ipv4.substring(0, ipv4.indexOf("/"));
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("ip-address", ipv4);
+ jsonArray.put(0, jsonObject);
+ return jsonArray;
+ }
+ }
+ return null;
+ }
+
+ public JSONObject innerLinkJsonNode() {
+ JSONObject root = new JSONObject();
+ JSONArray linkArray = new JSONArray();
+ int index = 0;
+ try {
+ for (Link link : internalLinks) {
+ JSONObject srcLinkNode = buildLinkNode(link.getSrcConnector());
+ if (srcLinkNode != null) {
+ linkArray.put(index, srcLinkNode);
+ index++;
+ }
+ JSONObject dstLinkNode = buildLinkNode(link.getDstConnector());
+ if (srcLinkNode != null) {
+ linkArray.put(index, dstLinkNode);
+ index++;
+ }
+ }
+ root.put("link", linkArray);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ return null;
+ }
+ return root;
+ }
+
+ private JSONObject buildLinkNode(Connector connector) {
+ Switch sw = switchMap.get(connector.getNodeName());
+ if (sw != null) {
+ JSONObject linkNode = new JSONObject();
+ String nodeId = "openflow:" + sw.getDataPathId();
+ String linkId = nodeId + ":" + connector.getOrder();
+ try {
+ linkNode.put("link-id", linkId);
+ linkNode.put("metric", "1");
+ linkNode.put("delay", "");
+ linkNode.put("loss-rate", "");
+ return linkNode;
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.models;
+
+import org.opendaylight.nemo.tool.sandbox.CmdExecutor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by hj on 12/8/15.
+ */
+abstract public class Node {
+ private static Logger log = LoggerFactory.getLogger(Node.class);
+ private final String name;
+ private final NodeType nodeType;
+ protected List<Connector> connectors;
+
+ public Node(NodeType nodeType, String name) {
+ this.nodeType = nodeType;
+ this.name = name;
+ this.connectors = new ArrayList<Connector>();
+ }
+
+ public NodeType getNodeType() {
+ return nodeType;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void addConnectors(Connector connector) {
+ connectors.add(connector);
+ }
+
+ public List<Connector> getConnectors() {
+ return connectors;
+ }
+
+ public void install() {
+ List<String> commands = generateCommands();
+ if (commands == null) {
+ log.error("Commands should not be null.");
+ return;
+ }
+ for (String command : commands) {
+ try {
+ CmdExecutor.sshExecute(command);
+ } catch (Exception e) {
+ log.error("Error while execute [{}].", command, name, nodeType);
+ e.printStackTrace();
+ }
+ }
+ }
+
+ abstract protected List<String> generateCommands();
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Node node = (Node) o;
+
+ if (name != null ? !name.equals(node.name) : node.name != null) return false;
+ if (nodeType != node.nodeType) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (nodeType != null ? nodeType.hashCode() : 0);
+ return result;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.models;
+
+/**
+ * Created by hj on 12/8/15.
+ */
+public enum NodeType {
+ SWITCH,ROUTER, VM,FIREWALL,CACHE,UNKNOWN
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.models;
+
+/**
+ * Created by hj on 12/8/15.
+ */
+public class Router extends Switch {
+ public Router(String name, long dataPathId) {
+ super(name, dataPathId);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.models;
+
+import org.opendaylight.nemo.tool.sandbox.utils.Config;
+import org.opendaylight.nemo.tool.sandbox.utils.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created by hj on 12/8/15.
+ */
+public class Switch extends Node {
+ private static Logger log = LoggerFactory.getLogger(Switch.class);
+ private final long dataPathId;
+ private final String mac;
+
+ public Switch(String name, long dataPathId) {
+ super(NodeType.SWITCH, name);
+ this.dataPathId = dataPathId;
+
+ this.mac = HexString.toHexString(dataPathId);
+ }
+
+ public long getDataPathId() {
+ return dataPathId;
+ }
+
+ @Override
+ protected List<String> generateCommands() {
+ List<String> commands = new ArrayList<String>();
+
+ String controllerSocket = Config.getControllerSocket();
+ String strInterface = "";
+ Collections.sort(connectors);
+ for (Connector connector : this.connectors) {
+ strInterface += ("," + connector.getConnectorName());
+ }
+ if (this.connectors.isEmpty()) {
+ log.warn("Switch {} does not have ports.");
+ strInterface = "";
+ } else {
+ strInterface = strInterface.substring(1);
+ }
+ String ofDataPathCreate = "ofdatapath";
+ if (!strInterface.equals("")) {
+ ofDataPathCreate += (" -i " + strInterface);
+ }
+ ofDataPathCreate += (" punix:/tmp/sw" + dataPathId + " -d " + mac + " 1> /tmp/sw" + dataPathId + "-ofd.log 2> /tmp/sw" + dataPathId + "-ofd.log &");
+ commands.add(ofDataPathCreate);
+
+ String ofProtocol = "ofprotocol unix:/tmp/sw" + dataPathId + " tcp:" + controllerSocket + " --fail=closed 1> /tmp/sw" + dataPathId + "-ofp.log 2>/tmp/sw" + dataPathId + "-ofp.log &";
+ commands.add(ofProtocol);
+ String lldp = "dpctl unix:/tmp/sw" + dataPathId + " flow-mod cmd=add,table=0 eth_type=0x88cc apply:output=ctrl:0xff";
+ commands.add(lldp);
+ String arp = "dpctl unix:/tmp/sw" + dataPathId + " flow-mod cmd=add,table=0 eth_type=0x0806 apply:output=ctrl:0xff";
+ commands.add(arp);
+
+ return commands;
+ }
+
+ @Override
+ public String toString() {
+ return "Switch{" +
+ "name=" + getName() +
+ ", dataPathId=" + dataPathId +
+ ", mac='" + mac + '\'' +
+ ", connectors=" + connectors +
+ '}';
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.models;
+
+import org.opendaylight.nemo.tool.sandbox.CmdExecutor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by hj on 12/8/15.
+ */
+public class VirtualMachine extends Host {
+ public VirtualMachine(String name,String uuId) {
+ super(NodeType.VM, name,uuId);
+ }
+
+ @Override
+ protected List<String> generateCommands() {
+ List<String> commands = new ArrayList<String>(generateHost());
+ //TODO: host script.
+ //open route flag
+ commands.add("ip netns exec "+getName()+"echo 1 > /proc/sys/net/ipv4/ip_forward");
+ //add default route
+ if(connectors.size()>0) {
+ commands.add("ip netns exec route add default dev "+ connectors.get(0));
+ }
+ return commands;
+ }
+
+ @Override
+ public void uninstall(){
+ try {
+ CmdExecutor.sshExecute("ip netns del " + getName());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.northbound;
+
+/**
+ * Created by hj on 12/12/15.
+ */
+public class CreateRequest {
+ public CreateRequest(){
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.northbound;
+
+/**
+ * Created by hj on 12/14/15.
+ */
+public class ExecuteRequest {
+ private String hostName;
+ private String command;
+
+ public ExecuteRequest(){
+
+ }
+
+ public String getHostName() {
+ return hostName;
+ }
+
+ public void setHostName(String hostName) {
+ this.hostName = hostName;
+ }
+
+ public String getCommand() {
+ return command;
+ }
+
+ public void setCommand(String command) {
+ this.command = command;
+ }
+
+ @Override
+ public String toString() {
+ return "ExecuteRequest{" +
+ "hostName='" + hostName + '\'' +
+ ", command='" + command + '\'' +
+ '}';
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.northbound;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import java.net.URI;
+
+public class RestServer {
+ // Base URI the Grizzly HTTP server will listen on
+ private static HttpServer server;
+
+ /**
+ * Starts Grizzly HTTP server exposing JAX-RS resources defined inN this application.
+ *
+ * @return Grizzly HTTP server.
+ */
+ public static void start(String socket) {
+ // create a resource config that scans for JAX-RS resources and providers
+ // in com.example package
+ final ResourceConfig rc = new ResourceConfig().packages("com.huawei.nemo.sandbox.northbound");
+
+ // create and start a new instance of grizzly http serverssss
+ // exposing the Jersey application at BASE_URI
+ server = GrizzlyHttpServerFactory.createHttpServer(URI.create(socket), rc);
+ }
+
+ public static void stop() {
+ if (server != null) {
+ server.shutdown();
+ server = null;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.northbound;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.codehaus.enunciate.jaxrs.TypeHint;
+import org.opendaylight.nemo.tool.sandbox.SandBoxManager;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by hj on 12/12/15.
+ */
+/**
+ * Root resource (exposed at "myresource" path)
+ */
+@Path("/nemo/sandbox")
+public class SandboxNorthbound {
+ @Path("/create")
+ @POST
+ @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Produces({MediaType.TEXT_PLAIN})
+ @StatusCodes
+ ({
+ @ResponseCode(code = 201, condition = "???"),
+ @ResponseCode(code = 409, condition = "")
+ })
+ public String create(
+ @Context UriInfo uriInfo,
+ String request) {
+ List<String> formattedCommands = format(request);
+ return "" + SandBoxManager.getInstance().createNetwork(formattedCommands);
+ }
+
+ private List<String> format(String request) {
+ String[] arrays = request.split("\n");
+ List<String> list = new ArrayList<String>();
+ for (String command : arrays) {
+ if (!command.trim().equals("")) {
+ list.add(command);
+ }
+ }
+ return list;
+ }
+
+// @Path("/create")
+// @POST
+// @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+// @Produces({MediaType.TEXT_PLAIN})
+// @StatusCodes
+// ({
+// @ResponseCode(code = 201, condition = "???"),
+// @ResponseCode(code = 409, condition = "")
+// })
+// public Response create(
+// @Context UriInfo uriInfo,
+// @TypeHint(CreateRequest.class) CreateRequest request) {
+// //TODO:Generate List<String> by the request.
+//
+// return Response.created(uriInfo.getRequestUri()).status(409).build();
+// }
+
+ @Path("/execute")
+ @POST
+ @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Produces({MediaType.TEXT_PLAIN})
+ @StatusCodes
+ ({
+ @ResponseCode(code = 201, condition = "???"),
+ @ResponseCode(code = 409, condition = "")
+ })
+ public String create(
+ @Context UriInfo uriInfo,
+ @TypeHint(ExecuteRequest.class) ExecuteRequest executeRequest) {
+ String result = SandBoxManager.getInstance().execute(executeRequest.getHostName(), executeRequest.getCommand());
+
+ return result;
+ }
+
+ @Path("/destroy")
+ @POST
+ @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Produces({MediaType.TEXT_PLAIN})
+ @StatusCodes
+ ({
+ @ResponseCode(code = 201, condition = "???"),
+ @ResponseCode(code = 409, condition = "")
+ })
+ public String destroy(@Context UriInfo uriInfo) {
+ //TODO:Generate List<String> by the request.
+ return SandBoxManager.getInstance().destroyNetwork() + "";
+ }
+
+ @Path("/crossdomain.xml")
+ @GET
+ @Produces({MediaType.TEXT_XML})
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful")})
+ public String getXml() {
+ System.out.println("getHosts running");
+ return "<?xml version=\"1.0\"?> <cross-domain-policy><allow-access-from domain=\"*\"/>" +
+ "<allow-http-request-headers-from domain=\"*\" headers=\"*\"/></cross-domain-policy>";
+ }
+
+ @Path("/hosts")
+ @GET
+ @Produces({MediaType.APPLICATION_JSON})
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful")})
+ public String getHosts() {
+ return SandBoxManager.getInstance().getHosts();
+ }
+
+ @Path("/switches")
+ @GET
+ @Produces({MediaType.APPLICATION_JSON})
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful")})
+ public String getSwitches() {
+ return SandBoxManager.getInstance().getSwitches();
+ }
+
+ @Path("/links")
+ @GET
+ @Produces({MediaType.APPLICATION_JSON})
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful")})
+ public String getLinks() {
+ return SandBoxManager.getInstance().getLinks();
+ }
+
+ @Path("/externals")
+ @GET
+ @Produces({MediaType.APPLICATION_JSON})
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful")})
+ public String getExternals() {
+ return SandBoxManager.getInstance().getExternals();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.utils;
+
+/**
+ * Created by hj on 12/8/15.
+ */
+public class Config {
+ private static String controllerSocket;
+ private static boolean printProcess;
+ private static String hostName;
+ private static String hostUser;
+ private static String hostPassword;
+
+ private static String configPath;
+ private static String configHostsFileName;
+ private static String configExternalsFileName;
+ private static String configLinksFileName;
+ private static String configNodesFileName;
+
+ static {
+ controllerSocket = System.getProperty("controller-socket","localhost:6633");
+ printProcess = Boolean.valueOf(System.getProperty("print-process","false"));
+ hostName = System.getProperty("host.name","localhost");
+ hostUser = System.getProperty("host.user","root");
+ hostPassword = System.getProperty("host.password","123456");
+ configPath = System.getProperty("config.path","/root");
+ configHostsFileName = System.getProperty("config.hosts-file-name","host-resource.json");
+ configExternalsFileName = System.getProperty("config.externals-file-name","external-resource.json");
+ configLinksFileName = System.getProperty("config.links-file-name","link-resource.json");
+ configNodesFileName = System.getProperty("config.nodes-file-name","node-resource.json");
+ }
+
+ public static String getControllerSocket(){
+ return controllerSocket;
+ }
+
+ public static boolean isPrintProcess(){
+ return printProcess;
+ }
+
+ public static String getHostName(){
+ return hostName;
+ }
+
+ public static String getHostUser(){
+ return hostUser;
+ }
+
+ public static String getHostPassword(){
+ return hostPassword;
+ }
+
+ public static String getConfigPath() {
+ return configPath;
+ }
+
+ public static String getConfigHostsFileName() {
+ return configHostsFileName;
+ }
+
+ public static String getConfigExternalsFileName() {
+ return configExternalsFileName;
+ }
+
+ public static String getConfigLinksFileName() {
+ return configLinksFileName;
+ }
+
+ public static String getConfigNodesFileName() {
+ return configNodesFileName;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.utils;
+
+import java.io.*;
+
+/**
+ * Created by hj on 12/11/15.
+ */
+public class FileUtils {
+ public static void write(String path, String content) {
+ try {
+ File f = new File(path);
+ if (!f.exists()) {
+ if (!f.createNewFile()) {
+ System.out.println("Can not create new file " + path);
+ }
+ }
+ BufferedWriter output = new BufferedWriter(new FileWriter(f));
+ output.write(content);
+ output.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.utils;
+
+import java.math.BigInteger;
+
+public class HexString {
+ public static String toHexString(long val, int padTo) {
+ char arr[] = Long.toHexString(val).toCharArray();
+ String ret = "";
+ // prepend the right number of leading zeros
+ int i = 0;
+ for (; i < (padTo * 2 - arr.length); i++) {
+ ret += "0";
+// if ((i % 2) != 0)
+// ret += ":";
+ }
+ for (int j = 0; j < arr.length; j++) {
+ ret += arr[j];
+// if ((((i + j) % 2) != 0) && (j < (arr.length - 1)))
+// ret += ":";
+ }
+ return ret;
+ }
+
+ public static String toHexString(long val) {
+ return toHexString(val, 6);
+ }
+
+ /**
+ * Convert a string of hex values into a string of bytes
+ *
+ * @param values "0f:ca:fe:de:ad:be:ef"
+ * @return [15, 5 ,2, 5, 17]
+ * @throws NumberFormatException If the string can not be parsed
+ */
+ public static byte[] fromHexString(String values) throws NumberFormatException {
+ String[] octets = values.split(":");
+ byte[] ret = new byte[octets.length];
+
+ for (int i = 0; i < octets.length; i++) {
+ if (octets[i].length() > 2)
+ throw new NumberFormatException("Invalid octet length");
+ ret[i] = Integer.valueOf(octets[i], 16).byteValue();
+ }
+ return ret;
+ }
+
+ public static long toLong(String values) throws NumberFormatException {
+ // Long.parseLong() can't handle HexStrings with MSB set. Sigh.
+ BigInteger bi = new BigInteger(values.replaceAll(":", ""), 16);
+ if (bi.bitLength() > 64)
+ throw new NumberFormatException("Input string too big to fit in long: " + values);
+ return bi.longValue();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.nemo.tool.sandbox.utils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by hj on 9/7/15.
+ */
+public class PropertyLoader {
+ public static void loadProperties(String filePath, String noExistWarn) {
+ try {
+ InputStream propFileStream = PropertyLoader.class.getClass().getResourceAsStream(filePath);
+ if (propFileStream != null)
+ System.getProperties().load(propFileStream);
+ else {
+ System.out.println(noExistWarn);
+ }
+ } catch (IOException e) {
+ System.out.println("Read properties file error:" + e.getMessage() + "!");
+ }
+ }
+
+ public static List<String> readLines(String filePath, String noExistWarn) {
+ List<String> lines = new ArrayList<String>();
+
+ try {
+ InputStream inputStream = PropertyLoader.class.getClass().getResourceAsStream(filePath);
+ if (inputStream != null) {
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ String line = null;
+ while ((line = bufferedReader.readLine()) != null) {
+ lines.add(line);
+ }
+ }else {
+ System.out.println(noExistWarn);
+ }
+ } catch (Exception e) {
+ System.out.println("Read lines error:" + e.getMessage() + "!");
+ }
+ return lines;
+ }
+}
--- /dev/null
+#switch:TYPE,NAME,DATA-PATH-ID
+#host:TYPE,NAME,UUID,Inde:IPV4,...
+#Link:TYPE,leftName,lPortId,rightName,rPortId
+
+Switch,sw1,1
+Router,sw2,2
+Firewall,firewall,1ab3cd4ef,1:192.168.1.1/16
+Link,sw1,1,sw2,1
+Link,sw1,2,firewall,1
\ No newline at end of file
--- /dev/null
+log4j.rootLogger=ERROR, stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
+
+log4j.logger.com.huawei.nemo=INFO
\ No newline at end of file
--- /dev/null
+host.name = 191.4.3.30
+host.user = root
+host.password = 123456
+controller-socket = 191.4.55.100:6633
+north.port = 10081
+config.path = /home/hj/configs
+config.hosts-file-name = nemo-openflow-render-host-resource.json
+config.externals-file-name = nemo-openflow-render-external-resource.json
+config.nodes-file-name = nemo-openflow-render-node-resource.json
+config.links-file-name = nemo-openflow-render-link-resource.json
+