Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/ClusterEvent.java b/core/api/src/main/java/org/onlab/onos/cluster/ClusterEvent.java
new file mode 100644
index 0000000..6737f68
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/cluster/ClusterEvent.java
@@ -0,0 +1,58 @@
+package org.onlab.onos.cluster;
+
+import org.onlab.onos.event.AbstractEvent;
+
+/**
+ * Describes cluster-related event.
+ */
+public class ClusterEvent extends AbstractEvent<ClusterEvent.Type, ControllerInstance> {
+
+ /**
+ * Type of device events.
+ */
+ public enum Type {
+ /**
+ * Signifies that a new cluster instance has been administratively added.
+ */
+ INSTANCE_ADDED,
+
+ /**
+ * Signifies that a cluster instance has been administratively removed.
+ */
+ INSTANCE_REMOVED,
+
+ /**
+ * Signifies that a cluster instance became active.
+ */
+ INSTANCE_ACTIVE,
+
+ /**
+ * Signifies that a cluster instance became inactive.
+ */
+ INSTANCE_INACTIVE
+ }
+ // TODO: do we need to fix the verv/adjective mix? discuss
+
+ /**
+ * Creates an event of a given type and for the specified instance and the
+ * current time.
+ *
+ * @param type cluster event type
+ * @param instance cluster device subject
+ */
+ public ClusterEvent(Type type, ControllerInstance instance) {
+ super(type, instance);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified device and time.
+ *
+ * @param type device event type
+ * @param instance event device subject
+ * @param time occurrence time
+ */
+ public ClusterEvent(Type type, ControllerInstance instance, long time) {
+ super(type, instance, time);
+ }
+
+}
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/ClusterService.java b/core/api/src/main/java/org/onlab/onos/cluster/ClusterService.java
new file mode 100644
index 0000000..afbf0d5
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/cluster/ClusterService.java
@@ -0,0 +1,29 @@
+package org.onlab.onos.cluster;
+
+import java.util.Set;
+
+/**
+ * Service for obtaining information about the individual instances within
+ * the controller cluster.
+ */
+public interface ClusterService {
+
+ /**
+ * Returns the set of current cluster members.
+ *
+ * @return set of cluster members
+ */
+ Set<ControllerInstance> getInstances();
+
+ /**
+ * Returns the availability state of the specified controller instance.
+ *
+ * @return availability state
+ */
+ ControllerInstance.State getState(ControllerInstance instance);
+ // TODO: determine if this would be better attached to ControllerInstance directly
+
+
+ // addListener, removeListener
+
+}
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/ControllerInstance.java b/core/api/src/main/java/org/onlab/onos/cluster/ControllerInstance.java
new file mode 100644
index 0000000..66d753e
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/cluster/ControllerInstance.java
@@ -0,0 +1,38 @@
+package org.onlab.onos.cluster;
+
+import org.onlab.packet.IpAddress;
+
+/**
+ * Represents a controller instance as a member in a cluster.
+ */
+public interface ControllerInstance {
+
+ /** Represents the operational state of the instance. */
+ public enum State {
+ /**
+ * Signifies that the instance is active and operating normally.
+ */
+ ACTIVE,
+
+ /**
+ * Signifies that the instance is inactive, which means either down or
+ * up, but not operational.
+ */
+ INACTIVE
+ }
+
+ /**
+ * Returns the instance identifier.
+ *
+ * @return instance identifier
+ */
+ InstanceId id();
+
+ /**
+ * Returns the IP address of the controller instance.
+ *
+ * @return IP address
+ */
+ IpAddress ip();
+
+}
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/InstanceId.java b/core/api/src/main/java/org/onlab/onos/cluster/InstanceId.java
new file mode 100644
index 0000000..7292a85
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/cluster/InstanceId.java
@@ -0,0 +1,7 @@
+package org.onlab.onos.cluster;
+
+/**
+ * Controller cluster identity.
+ */
+public interface InstanceId {
+}
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/package-info.java b/core/api/src/main/java/org/onlab/onos/cluster/package-info.java
new file mode 100644
index 0000000..3cb37c3
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/cluster/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Set of abstractions for dealing with controller cluster related topics.
+ */
+package org.onlab.onos.cluster;
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowEntry.java b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowEntry.java
index 3f86697..295517b 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowEntry.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowEntry.java
@@ -1,5 +1,7 @@
package org.onlab.onos.net.flow;
+import static com.google.common.base.MoreObjects.toStringHelper;
+
import org.onlab.onos.net.DeviceId;
public class DefaultFlowEntry extends DefaultFlowRule implements FlowEntry {
@@ -63,7 +65,9 @@
public int hashCode() {
final int prime = 31;
int result = prime * this.deviceId().hashCode();
- result = prime * result + Long.valueOf(this.created).hashCode();
+ result = prime * result + this.priority;
+ result = prime * result + this.selector().hashCode();
+ result = prime * result + this.treatment().hashCode();
return result;
}
@@ -77,7 +81,10 @@
public boolean equals(Object obj) {
if (obj instanceof DefaultFlowEntry) {
DefaultFlowEntry that = (DefaultFlowEntry) obj;
- if (!this.id.equals(that.id())) {
+ if (!this.deviceId().equals(that.deviceId())) {
+ return false;
+ }
+ if (!(this.priority == that.priority)) {
return false;
}
return super.equals(obj);
@@ -85,4 +92,15 @@
return false;
}
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("id", id)
+ .add("deviceId", deviceId())
+ .add("priority", priority)
+ .add("selector", selector())
+ .add("treatment", treatment())
+ .toString();
+ }
+
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
index 9a24091..d20e79e 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
@@ -17,6 +17,7 @@
@Override
public int priority() {
+ // is this supposed to be 0?
return 0;
}
@@ -63,8 +64,9 @@
if (!this.selector().equals(that.selector())) {
return false;
}
+ return true;
}
- return true;
+ return false;
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleEvent.java b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleEvent.java
index 566c2b4..ce8e700 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleEvent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleEvent.java
@@ -19,7 +19,7 @@
/**
* Signifies that a flow rule has been removed.
*/
- RULE_REMOVED,
+ RULE_REMOVED
}
/**
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleService.java b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleService.java
index 71434c7..ba75ae9 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleService.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleService.java
@@ -23,6 +23,8 @@
*/
Iterable<FlowEntry> getFlowEntries(DeviceId deviceId);
+ // TODO: add createFlowRule factory method and execute operations method
+
/**
* Applies the specified flow rules onto their respective devices. These
* flow rules will be retained by the system and re-applied anytime the
@@ -46,9 +48,6 @@
void removeFlowRules(FlowRule... flowRules);
- // void addInitialFlowContributor(InitialFlowContributor contributor);
- // void removeInitialFlowContributor(InitialFlowContributor contributor);
-
/**
* Adds the specified flow rule listener.
*
diff --git a/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleManager.java b/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleManager.java
index 30238c4..b7c5b15 100644
--- a/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleManager.java
+++ b/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleManager.java
@@ -44,10 +44,10 @@
private final SimpleFlowRuleStore store = new SimpleFlowRuleStore();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- private EventDeliveryService eventDispatcher;
+ protected EventDeliveryService eventDispatcher;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- private DeviceService deviceService;
+ protected DeviceService deviceService;
@Activate
public void activate() {
diff --git a/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleStore.java b/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleStore.java
index f839396..4f23ff4 100644
--- a/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleStore.java
+++ b/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleStore.java
@@ -53,17 +53,20 @@
FlowRuleEvent addOrUpdateFlowRule(FlowRule rule) {
DeviceId did = rule.deviceId();
+ FlowEntry entry = new DefaultFlowEntry(
+ did,
+ rule.selector(),
+ rule.treatment(),
+ rule.priority());
+
// check if this new rule is an update to an existing entry
for (FlowEntry fe : flowEntries.get(did)) {
- if (rule.equals(fe)) {
+ if (entry.equals(fe)) {
// TODO update the stats on this flowEntry?
return null;
}
}
-
- FlowEntry newfe = new DefaultFlowEntry(did,
- rule.selector(), rule.treatment(), rule.priority());
- flowEntries.put(did, newfe);
+ flowEntries.put(did, entry);
return new FlowRuleEvent(RULE_ADDED, rule);
}
@@ -73,8 +76,11 @@
* @return flow_removed event, or null if nothing removed
*/
FlowRuleEvent removeFlowRule(FlowRule rule) {
+
+ FlowEntry rem = new DefaultFlowEntry(rule.deviceId(),
+ rule.selector(), rule.treatment(), rule.priority());
synchronized (this) {
- if (flowEntries.remove(rule.deviceId(), rule)) {
+ if (flowEntries.remove(rem.deviceId(), rem)) {
return new FlowRuleEvent(RULE_REMOVED, rule);
} else {
return null;
diff --git a/core/trivial/src/test/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleManagerTest.java b/core/trivial/src/test/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleManagerTest.java
new file mode 100644
index 0000000..bb0a496
--- /dev/null
+++ b/core/trivial/src/test/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleManagerTest.java
@@ -0,0 +1,322 @@
+package org.onlab.onos.net.trivial.flow.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.onos.event.impl.TestEventDispatcher;
+import org.onlab.onos.net.DefaultDevice;
+import org.onlab.onos.net.Device;
+import org.onlab.onos.net.Device.Type;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.MastershipRole;
+import org.onlab.onos.net.Port;
+import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.device.DeviceListener;
+import org.onlab.onos.net.device.DeviceService;
+import org.onlab.onos.net.flow.DefaultFlowEntry;
+import org.onlab.onos.net.flow.DefaultFlowRule;
+import org.onlab.onos.net.flow.FlowEntry;
+import org.onlab.onos.net.flow.FlowRule;
+import org.onlab.onos.net.flow.FlowRuleEvent;
+import org.onlab.onos.net.flow.FlowRuleListener;
+import org.onlab.onos.net.flow.FlowRuleProvider;
+import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
+import org.onlab.onos.net.flow.FlowRuleProviderService;
+import org.onlab.onos.net.flow.FlowRuleService;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.flow.criteria.Criterion;
+import org.onlab.onos.net.flow.instructions.Instruction;
+import org.onlab.onos.net.provider.AbstractProvider;
+import org.onlab.onos.net.provider.ProviderId;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+import static org.onlab.onos.net.flow.FlowRuleEvent.Type.*;
+
+/**
+ * Test codifying the flow rule service & flow rule provider service contracts.
+ */
+public class SimpleFlowRuleManagerTest {
+
+ private static final ProviderId PID = new ProviderId("foo");
+ private static final DeviceId DID = DeviceId.deviceId("of:001");
+ private static final Device DEV = new DefaultDevice(
+ PID, DID, Type.SWITCH, "", "", "", "");
+
+ private SimpleFlowRuleManager mgr;
+
+ protected FlowRuleService service;
+ protected FlowRuleProviderRegistry registry;
+ protected FlowRuleProviderService providerSerivce;
+ protected TestProvider provider;
+ protected TestListener listener = new TestListener();
+
+ @Before
+ public void setUp() {
+ mgr = new SimpleFlowRuleManager();
+ mgr.eventDispatcher = new TestEventDispatcher();
+ mgr.deviceService = new TestDeviceService();
+ service = mgr;
+ registry = mgr;
+
+ mgr.activate();
+ mgr.addListener(listener);
+ provider = new TestProvider(PID);
+ providerSerivce = registry.register(provider);
+ assertTrue("provider should be registered",
+ registry.getProviders().contains(provider.id()));
+ }
+
+ @After
+ public void tearDown() {
+ registry.unregister(provider);
+ assertFalse("provider should not be registered",
+ registry.getProviders().contains(provider.id()));
+ service.removeListener(listener);
+ mgr.deactivate();
+ mgr.eventDispatcher = null;
+ mgr.deviceService = null;
+ }
+
+ private FlowRule flowRule(int tsval, int trval) {
+ TestSelector ts = new TestSelector(tsval);
+ TestTreatment tr = new TestTreatment(trval);
+ return new DefaultFlowRule(DID, ts, tr);
+ }
+
+ private void addFlowRule(int hval) {
+ FlowRule rule = flowRule(hval, hval);
+ providerSerivce.flowAdded(rule);
+ assertNotNull("rule should be found", service.getFlowEntries(DID));
+ }
+
+ private void validateEvents(FlowRuleEvent.Type ... events) {
+ if (events == null) {
+ assertTrue("events generated", listener.events.isEmpty());
+ }
+
+ int i = 0;
+ for (FlowRuleEvent e : listener.events) {
+ assertTrue("unexpected event", e.type().equals(events[i]));
+ i++;
+ }
+
+ assertEquals("mispredicted number of events",
+ events.length, listener.events.size());
+
+ listener.events.clear();
+ }
+
+ private int flowCount() {
+ return Sets.newHashSet(service.getFlowEntries(DID)).size();
+ }
+ @Test
+ public void getFlowEntries() {
+ assertTrue("store should be empty",
+ Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
+ addFlowRule(1);
+ addFlowRule(2);
+ assertEquals("2 rules should exist", 2, flowCount());
+ validateEvents(RULE_ADDED, RULE_ADDED);
+
+ addFlowRule(1);
+ assertEquals("should still be 2 rules", 2, flowCount());
+ validateEvents();
+ }
+
+ @Test
+ public void applyFlowRules() {
+ TestSelector ts = new TestSelector(1);
+ FlowRule r1 = flowRule(1, 1);
+ FlowRule r2 = flowRule(1, 2);
+ FlowRule r3 = flowRule(1, 3);
+
+ //current FlowRules always return 0. FlowEntries inherit the value
+ FlowEntry e1 = new DefaultFlowEntry(DID, ts, r1.treatment(), 0);
+ FlowEntry e2 = new DefaultFlowEntry(DID, ts, r2.treatment(), 0);
+ FlowEntry e3 = new DefaultFlowEntry(DID, ts, r3.treatment(), 0);
+ List<FlowEntry> fel = Lists.newArrayList(e1, e2, e3);
+
+ assertTrue("store should be empty",
+ Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
+ List<FlowEntry> ret = mgr.applyFlowRules(r1, r2, r3);
+ assertEquals("3 rules should exist", 3, flowCount());
+ assertTrue("3 entries should result", fel.containsAll(ret));
+ }
+
+ @Test
+ public void removeFlowRules() {
+ addFlowRule(1);
+ addFlowRule(2);
+ addFlowRule(3);
+ assertEquals("3 rules should exist", 3, flowCount());
+ validateEvents(RULE_ADDED, RULE_ADDED, RULE_ADDED);
+
+ FlowRule rem1 = flowRule(1, 1);
+ FlowRule rem2 = flowRule(2, 2);
+ mgr.removeFlowRules(rem1, rem2);
+ //removing from north, so no events generated
+ validateEvents();
+ assertEquals("1 rule should exist", 1, flowCount());
+
+ mgr.removeFlowRules(rem1);
+ assertEquals("1 rule should still exist", 1, flowCount());
+ }
+
+ @Test
+ public void flowRemoved() {
+ addFlowRule(1);
+ addFlowRule(2);
+ FlowRule rem1 = flowRule(1, 1);
+ providerSerivce.flowRemoved(rem1);
+ validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
+
+ providerSerivce.flowRemoved(rem1);
+ validateEvents();
+ }
+
+ private static class TestListener implements FlowRuleListener {
+ final List<FlowRuleEvent> events = new ArrayList<>();
+
+ @Override
+ public void event(FlowRuleEvent event) {
+ events.add(event);
+ }
+ }
+
+ private static class TestDeviceService implements DeviceService {
+
+ @Override
+ public int getDeviceCount() {
+ return 0;
+ }
+
+ @Override
+ public Iterable<Device> getDevices() {
+ return null;
+ }
+
+ @Override
+ public Device getDevice(DeviceId deviceId) {
+ return DEV;
+ }
+
+ @Override
+ public MastershipRole getRole(DeviceId deviceId) {
+ return null;
+ }
+
+ @Override
+ public List<Port> getPorts(DeviceId deviceId) {
+ return null;
+ }
+
+ @Override
+ public Port getPort(DeviceId deviceId, PortNumber portNumber) {
+ return null;
+ }
+
+ @Override
+ public boolean isAvailable(DeviceId deviceId) {
+ return false;
+ }
+
+ @Override
+ public void addListener(DeviceListener listener) {
+ }
+
+ @Override
+ public void removeListener(DeviceListener listener) {
+ }
+
+ }
+
+ private class TestProvider extends AbstractProvider implements FlowRuleProvider {
+
+ protected TestProvider(ProviderId id) {
+ super(PID);
+ }
+
+ @Override
+ public void applyFlowRule(FlowRule... flowRules) {
+ }
+
+ @Override
+ public void removeFlowRule(FlowRule... flowRules) {
+ }
+
+ @Override
+ public Iterable<FlowEntry> getFlowMetrics(DeviceId deviceId) {
+ return null;
+ }
+
+ }
+
+ private class TestSelector implements TrafficSelector {
+
+ //for controlling hashcode uniqueness;
+ private int testval;
+
+ public TestSelector(int val) {
+ testval = val;
+ }
+
+ @Override
+ public List<Criterion> criteria() {
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ return testval;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof TestSelector) {
+ return this.testval == ((TestSelector) o).testval;
+ }
+ return false;
+ }
+ }
+
+ private class TestTreatment implements TrafficTreatment {
+
+ //for controlling hashcode uniqueness;
+ private int testval;
+
+ public TestTreatment(int val) {
+ testval = val;
+ }
+
+ @Override
+ public List<Instruction> instructions() {
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ return testval;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof TestTreatment) {
+ return this.testval == ((TestTreatment) o).testval;
+ }
+ return false;
+ }
+
+ }
+
+}
diff --git a/features/features.xml b/features/features.xml
index 6d981a8..92c0511 100644
--- a/features/features.xml
+++ b/features/features.xml
@@ -7,7 +7,6 @@
description="ONOS 3rd party dependencies">
<bundle>mvn:commons-lang/commons-lang/2.6</bundle>
<bundle>mvn:com.google.guava/guava/18.0</bundle>
-
<bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
</feature>
@@ -63,7 +62,7 @@
<feature name="onos-openflow" version="1.0.0"
description="ONOS OpenFlow API, Controller & Providers">
<feature>onos-api</feature>
-
+ <bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
<bundle>mvn:org.onlab.onos/onos-of-api/1.0.0-SNAPSHOT</bundle>
<bundle>mvn:org.onlab.onos/onos-of-ctl/1.0.0-SNAPSHOT</bundle>
@@ -77,8 +76,9 @@
<feature name="onos-app-tvue" version="1.0.0"
description="ONOS sample topology viewer application">
- <feature>onos-api</feature>
<feature>onos-thirdparty-web</feature>
+ <feature>onos-api</feature>
+ <feature>onos-core</feature>
<bundle>mvn:org.onlab.onos/onos-app-tvue/1.0.0-SNAPSHOT</bundle>
</feature>
diff --git a/openflow/ctl/pom.xml b/openflow/ctl/pom.xml
index 88bdcd9..4bd7619 100644
--- a/openflow/ctl/pom.xml
+++ b/openflow/ctl/pom.xml
@@ -15,107 +15,27 @@
<description>ONOS OpenFlow controller subsystem API</description>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <powermock.version>1.5.5</powermock.version>
- <restlet.version>2.1.4</restlet.version>
- <cobertura-maven-plugin.version>2.6</cobertura-maven-plugin.version>
- <!-- Following 2 findbugs version needs to be updated in sync to match the
- findbugs version used in findbugs-plugin -->
- <findbugs.version>3.0.0</findbugs.version>
- <findbugs-plugin.version>3.0.0</findbugs-plugin.version>
- <findbugs.effort>Max</findbugs.effort>
- <findbugs.excludeFilterFile>${project.basedir}/conf/findbugs/exclude.xml
- </findbugs.excludeFilterFile>
- <checkstyle-plugin.version>2.12</checkstyle-plugin.version>
- <!-- To publish javadoc to github,
- uncomment com.github.github site-maven-plugin and
- see https://github.com/OPENNETWORKINGLAB/ONOS/pull/425
- <github.global.server>github</github.global.server>
- -->
- <metrics.version>3.0.2</metrics.version>
- <maven.surefire.plugin.version>2.16</maven.surefire.plugin.version>
- </properties>
-
<dependencies>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-of-api</artifactId>
</dependency>
- <!-- ONOS's direct dependencies -->
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
- <version>1.9.6</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- <version>1.1.2</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-core</artifactId>
- <version>1.1.2</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <version>1.7.5</version>
- </dependency>
- <dependency>
- <!-- findbugs suppression annotation and @GuardedBy, etc. -->
- <groupId>com.google.code.findbugs</groupId>
- <artifactId>annotations</artifactId>
- <version>${findbugs.version}</version>
- </dependency>
- <dependency>
- <groupId>org.projectfloodlight</groupId>
- <artifactId>openflowj</artifactId>
- <version>0.3.8-SNAPSHOT</version>
- </dependency>
- <!-- Floodlight's dependencies -->
- <dependency>
- <!-- dependency to old version of netty? -->
- <groupId>io.netty</groupId>
- <artifactId>netty</artifactId>
- <version>3.9.2.Final</version>
- </dependency>
- <!-- Dependency for libraries used for testing -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.11</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.easymock</groupId>
- <artifactId>easymock</artifactId>
- <version>3.2</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-module-junit4</artifactId>
- <version>${powermock.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-api-easymock</artifactId>
- <version>${powermock.version}</version>
- <scope>test</scope>
</dependency>
</dependencies>
-
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
-
</plugins>
</build>
diff --git a/tools/build/envDefaults b/tools/build/envDefaults
new file mode 100644
index 0000000..71d4cf4
--- /dev/null
+++ b/tools/build/envDefaults
@@ -0,0 +1,22 @@
+# Environmental defaults for ONOS build, package and test
+
+# Root of the ONOS source tree
+export ONOS_ROOT=${ONOS_ROOT:-~/onos-next}
+
+# M2 repository and Karaf gold bits
+export M2_REPO=${M2_REPO:-~/.m2/repository}
+export KARAF_ZIP=${KARAF_ZIP:-~/Downloads/apache-karaf-3.0.1.zip}
+export KARAF_DIST=$(basename $KARAF_ZIP .zip)
+
+# ONOS Version and onos.tar.gz staging environment
+export ONOS_VERSION=${ONOS_VERSION:-1.0.0-SNAPSHOT}
+export ONOS_STAGE_ROOT=${ONOS_STAGE_ROOT:-/tmp}
+export ONOS_BITS=onos-$ONOS_VERSION
+export ONOS_STAGE=$ONOS_STAGE_ROOT/$ONOS_BITS
+export ONOS_TAR=$ONOS_STAGE.tar.gz
+
+# Defaults for ONOS testing using remote machines.
+export ONOS_INSTALL_DIR="/opt/onos" # Installation directory on remote
+export OCI="${OCI:-192.168.56.101}" # ONOS Controller Instance
+export ONOS_USER="sdn" # ONOS user on remote system
+export ONOS_PWD="rocks" # ONOS user password on remote system
diff --git a/tools/package/package b/tools/build/onos-package
similarity index 61%
rename from tools/package/package
rename to tools/build/onos-package
index 0bf8a39..5918306 100755
--- a/tools/package/package
+++ b/tools/build/onos-package
@@ -3,14 +3,8 @@
# Packages ONOS distributable into onos.tar.gz
#-------------------------------------------------------------------------------
-export M2_REPO=${M2_REPO:-~/.m2/repository}
-export KARAF_ZIP=${KARAF_ZIP:-~/Downloads/apache-karaf-3.0.1.zip}
-export KARAF_DIST=$(basename $KARAF_ZIP .zip)
-
-export ONOS_VERSION=${ONOS_VERSION:-1.0.0-SNAPSHOT}
-export ONOS_STAGE_ROOT=${ONOS_STAGE_ROOT:-/tmp}
-export ONOS_BITS=onos-$ONOS_VERSION
-export ONOS_STAGE=$ONOS_STAGE_ROOT/$ONOS_BITS
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
# Bail on any errors
set -e
@@ -26,29 +20,31 @@
mkdir -p $ONOS_STAGE
cd $ONOS_STAGE
-# Unroll the Apache Karaf bits and make the ONOS top-level directories.
-unzip $KARAF_ZIP
+# Unroll the Apache Karaf bits, prune them and make ONOS top-level directories.
+unzip -q $KARAF_ZIP && rm -rf $KARAF_DIST/demos
mkdir bin
-# Stage the ONOS admin scripts
+# Stage the ONOS admin scripts and patch in Karaf service wrapper extras
cp -r $ONOS_ROOT/tools/package/bin .
+cp -r $ONOS_ROOT/tools/package/wrapper/* $KARAF_DIST
# Stage the ONOS bundles
-mkdir -p system/org/onlab
-cp -r $M2_REPO/org/onlab system/org/
+mkdir -p $KARAF_DIST/system/org/onlab
+cp -r $M2_REPO/org/onlab $KARAF_DIST/system/org/
# Patch the Apache Karaf distribution file to add ONOS features repository
perl -pi.old -e "s|^(featuresRepositories=.*)|\1,mvn:org.onlab.onos/onos-features/$ONOS_VERSION/xml/features|" \
$ONOS_STAGE/$KARAF_DIST/etc/org.apache.karaf.features.cfg
# Patch the Apache Karaf distribution file to load ONOS features
-perl -pi.old -e 's|^(featuresBoot=.*)|\1,onos-api,onos-core,onos-cli,onos-rest,onos-gui,onos-openflow,onos-app-tvue|' \
- /tmp/onos-1.0.0-SNAPSHOT/apache-karaf-3.0.1/etc/org.apache.karaf.features.cfg
+perl -pi.old -e 's|^(featuresBoot=.*)|\1,wrapper,onos-api,onos-core,onos-cli,onos-rest,onos-gui,onos-openflow,onos-app-tvue|' \
+ $ONOS_STAGE/$KARAF_DIST/etc/org.apache.karaf.features.cfg
# Patch the Apache Karaf distribution with ONOS branding bundle
cp $M2_REPO/org/onlab/onos/onos-branding/$ONOS_VERSION/onos-branding-*.jar \
- $ONOS_STAGE/apache-karaf-*/lib
+ $ONOS_STAGE/$KARAF_DIST/lib
# Now package up the ONOS tar file
cd $ONOS_STAGE_ROOT
-tar zcf $ONOS_BITS.tar.gz $ONOS_BITS
+COPYFILE_DISABLE=1 tar zcf $ONOS_TAR $ONOS_BITS
+ls -l $ONOS_TAR >&2
diff --git a/tools/dev/bash_profile b/tools/dev/bash_profile
index a9852ba..cc19a4d 100644
--- a/tools/dev/bash_profile
+++ b/tools/dev/bash_profile
@@ -12,7 +12,8 @@
# Setup a path
export PS=":"
-export PATH="$PATH:$ONOS_ROOT/tools/dev:$ONOS_ROOT/tools/package"
+export PATH="$PATH:$ONOS_ROOT/tools/dev:$ONOS_ROOT/tools/build"
+export PATH="$PATH:$ONOS_ROOT/tools/test/bin"
export PATH="$PATH:$MAVEN/bin:$KARAF/bin"
export PATH="$PATH:."
@@ -39,3 +40,13 @@
# Short-hand to launch API docs and sample topology viewer GUI
alias docs='open $ONOS_ROOT/target/site/apidocs/index.html'
alias gui='open http://localhost:8181/onos/tvue'
+
+
+# Miscellaneous
+function spy {
+ ps -ef | egrep "$@" | grep -v egrep
+}
+
+function nuke {
+ spy | cut -c7-11 | xargs kill
+}
diff --git a/tools/package/README b/tools/package/README
new file mode 100644
index 0000000..3a2e4ff
--- /dev/null
+++ b/tools/package/README
@@ -0,0 +1 @@
+Artifacts for packaging onos.tar.gz.
diff --git a/tools/package/bin/onos b/tools/package/bin/onos
new file mode 100755
index 0000000..a59ada2
--- /dev/null
+++ b/tools/package/bin/onos
@@ -0,0 +1,10 @@
+#!/bin/bash
+#-------------------------------------------------------------------------------
+# ONOS command-line client
+#-------------------------------------------------------------------------------
+
+export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64/
+
+cd $(dirname $0)/../apache-karaf-*/bin
+./client -h localhost "$@"
+
diff --git a/tools/package/bin/onos-ctl b/tools/package/bin/onos-ctl
index 2c6097d..e5ffe87 100755
--- a/tools/package/bin/onos-ctl
+++ b/tools/package/bin/onos-ctl
@@ -3,6 +3,8 @@
# Starts ONOS Apache Karaf container
#-------------------------------------------------------------------------------
+export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64/
+
cd $(dirname $0)/../apache-karaf-*/bin
./karaf "$@"
diff --git a/tools/package/wrapper/bin/onos-service b/tools/package/wrapper/bin/onos-service
new file mode 100755
index 0000000..27da7a3
--- /dev/null
+++ b/tools/package/wrapper/bin/onos-service
@@ -0,0 +1,557 @@
+#! /bin/sh
+
+# ------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ------------------------------------------------------------------------
+
+# If require, set the JAVA_HOME to launch the wrapper
+#
+#JAVA_HOME=
+#
+
+# Application
+APP_NAME="onos"
+APP_LONG_NAME="onos"
+
+# Wrapper
+WRAPPER_CMD="/opt/onos/apache-karaf-3.0.1/bin/${APP_NAME}-wrapper"
+WRAPPER_CONF="/opt/onos/apache-karaf-3.0.1/etc/${APP_NAME}-wrapper.conf"
+
+# Priority at which to run the wrapper. See "man nice" for valid priorities.
+# nice is only used if a priority is specified.
+PRIORITY=
+
+# Location of the data folder.
+DATADIR="/opt/onos/apache-karaf-3.0.1/data"
+
+# Location of the pid file.
+PIDDIR="/opt/onos/apache-karaf-3.0.1/data"
+
+# If uncommented, causes the Wrapper to be shutdown using an anchor file.
+# When launched with the 'start' command, it will also ignore all INT and
+# TERM signals.
+#IGNORE_SIGNALS=true
+
+# If specified, the Wrapper will be run as the specified user.
+# IMPORTANT - Make sure that the user has the required privileges to write
+# the PID file and wrapper.log files. Failure to be able to write the log
+# file will cause the Wrapper to exit without any way to write out an error
+# message.
+# NOTE - This will set the user which is used to run the Wrapper as well as
+# the JVM and is not useful in situations where a privileged resource or
+# port needs to be allocated prior to the user being changed.
+#RUN_AS_USER=
+
+# The following two lines are used by the chkconfig command. Change as is
+# appropriate for your application. They should remain commented.
+# chkconfig: 2345 20 80
+# description: onos
+
+# Do not modify anything beyond this point
+#-----------------------------------------------------------------------------
+
+# Get the fully qualified path to the script
+case $0 in
+ /*)
+ SCRIPT="$0"
+ ;;
+ *)
+ PWD=`pwd`
+ SCRIPT="$PWD/$0"
+ ;;
+esac
+
+# Resolve the true real path without any sym links.
+CHANGED=true
+while [ "X$CHANGED" != "X" ]
+do
+ # Change spaces to ":" so the tokens can be parsed.
+ SCRIPT=`echo $SCRIPT | sed -e 's; ;:;g'`
+ # Get the real path to this script, resolving any symbolic links
+ TOKENS=`echo $SCRIPT | sed -e 's;/; ;g'`
+ REALPATH=
+ for C in $TOKENS; do
+ REALPATH="$REALPATH/$C"
+ while [ -h "$REALPATH" ] ; do
+ LS="`ls -ld "$REALPATH"`"
+ LINK="`expr "$LS" : '.*-> \(.*\)$'`"
+ if expr "$LINK" : '/.*' > /dev/null; then
+ REALPATH="$LINK"
+ else
+ REALPATH="`dirname "$REALPATH"`""/$LINK"
+ fi
+ done
+ done
+ # Change ":" chars back to spaces.
+ REALPATH=`echo $REALPATH | sed -e 's;:; ;g'`
+
+ if [ "$REALPATH" = "$SCRIPT" ]
+ then
+ CHANGED=""
+ else
+ SCRIPT="$REALPATH"
+ fi
+done
+
+# Change the current directory to the location of the script
+cd "`dirname "$REALPATH"`"
+REALDIR=`pwd`
+
+# If the PIDDIR is relative, set its value relative to the full REALPATH to avoid problems if
+# the working directory is later changed.
+FIRST_CHAR=`echo $PIDDIR | cut -c1,1`
+if [ "$FIRST_CHAR" != "/" ]
+then
+ PIDDIR=$REALDIR/$PIDDIR
+fi
+# Same test for WRAPPER_CMD
+FIRST_CHAR=`echo $WRAPPER_CMD | cut -c1,1`
+if [ "$FIRST_CHAR" != "/" ]
+then
+ WRAPPER_CMD=$REALDIR/$WRAPPER_CMD
+fi
+# Same test for WRAPPER_CONF
+FIRST_CHAR=`echo $WRAPPER_CONF | cut -c1,1`
+if [ "$FIRST_CHAR" != "/" ]
+then
+ WRAPPER_CONF=$REALDIR/$WRAPPER_CONF
+fi
+
+# Process ID
+ANCHORFILE="$PIDDIR/$APP_NAME.anchor"
+PIDFILE="$PIDDIR/$APP_NAME.pid"
+LOCKDIR="/var/lock/subsys"
+LOCKFILE="$LOCKDIR/$APP_NAME"
+pid=""
+
+# Resolve the location of the 'ps' command
+PSEXE="/usr/bin/ps"
+if [ ! -x $PSEXE ]
+then
+ PSEXE="/bin/ps"
+ if [ ! -x $PSEXE ]
+ then
+ echo "Unable to locate 'ps'."
+ echo "Please report this message along with the location of the command on your system."
+ exit 1
+ fi
+fi
+
+# Resolve the os
+DIST_OS=`uname -s | tr [:upper:] [:lower:] | tr -d [:blank:]`
+case "$DIST_OS" in
+ 'sunos')
+ DIST_OS="solaris"
+ ;;
+ 'hp-ux' | 'hp-ux64')
+ DIST_OS="hpux"
+ ;;
+ 'darwin')
+ DIST_OS="macosx"
+ ;;
+ 'unix_sv')
+ DIST_OS="unixware"
+ ;;
+esac
+
+# Resolve the architecture
+DIST_ARCH=`uname -p | tr [:upper:] [:lower:] | tr -d [:blank:]`
+if [ "$DIST_ARCH" = "unknown" ]
+then
+ DIST_ARCH=`uname -m | tr [:upper:] [:lower:] | tr -d [:blank:]`
+fi
+case "$DIST_ARCH" in
+ 'amd64' | 'ia32' | 'ia64' | 'i386' | 'i486' | 'i586' | 'i686' | 'x86_64')
+ DIST_ARCH="x86"
+ ;;
+ 'ip27')
+ DIST_ARCH="mips"
+ ;;
+ 'power' | 'powerpc' | 'power_pc' | 'ppc64')
+ DIST_ARCH="ppc"
+ ;;
+ 'pa_risc' | 'pa-risc')
+ DIST_ARCH="parisc"
+ ;;
+ 'sun4u' | 'sparcv9')
+ DIST_ARCH="sparc"
+ ;;
+ '9000/800')
+ DIST_ARCH="parisc"
+ ;;
+esac
+
+# Decide on the wrapper binary to use.
+# If a 32-bit wrapper binary exists then it will work on 32 or 64 bit
+# platforms, if the 64-bit binary exists then the distribution most
+# likely wants to use long names. Otherwise, look for the default.
+# For macosx, we also want to look for universal binaries.
+WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
+if [ -x $WRAPPER_TEST_CMD ]
+then
+ WRAPPER_CMD="$WRAPPER_TEST_CMD"
+else
+ if [ "$DIST_OS" = "macosx" ]
+ then
+ WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-universal-32"
+ if [ -x $WRAPPER_TEST_CMD ]
+ then
+ WRAPPER_CMD="$WRAPPER_TEST_CMD"
+ else
+ WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
+ if [ -x $WRAPPER_TEST_CMD ]
+ then
+ WRAPPER_CMD="$WRAPPER_TEST_CMD"
+ else
+ WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-universal-64"
+ if [ -x $WRAPPER_TEST_CMD ]
+ then
+ WRAPPER_CMD="$WRAPPER_TEST_CMD"
+ else
+ if [ ! -x $WRAPPER_CMD ]
+ then
+ echo "Unable to locate any of the following binaries:"
+ echo " $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
+ echo " $WRAPPER_CMD-$DIST_OS-universal-32"
+ echo " $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
+ echo " $WRAPPER_CMD-$DIST_OS-universal-64"
+ echo " $WRAPPER_CMD"
+ exit 1
+ fi
+ fi
+ fi
+ fi
+ else
+ WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
+ if [ -x $WRAPPER_TEST_CMD ]
+ then
+ WRAPPER_CMD="$WRAPPER_TEST_CMD"
+ else
+ if [ ! -x $WRAPPER_CMD ]
+ then
+ echo "Unable to locate any of the following binaries:"
+ echo " $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
+ echo " $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
+ echo " $WRAPPER_CMD"
+ exit 1
+ fi
+ fi
+ fi
+fi
+
+# Build the nice clause
+if [ "X$PRIORITY" = "X" ]
+then
+ CMDNICE=""
+else
+ CMDNICE="nice -$PRIORITY"
+fi
+
+# Build the anchor file clause.
+if [ "X$IGNORE_SIGNALS" = "X" ]
+then
+ ANCHORPROP=
+ IGNOREPROP=
+else
+ ANCHORPROP=wrapper.anchorfile=$ANCHORFILE
+ IGNOREPROP=wrapper.ignore_signals=TRUE
+fi
+
+# Build the lock file clause. Only create a lock file if the lock directory exists on this platform.
+if [ -d $LOCKDIR ]
+then
+ LOCKPROP=wrapper.lockfile=$LOCKFILE
+else
+ LOCKPROP=
+fi
+
+checkUser() {
+ # Check the configured user. If necessary rerun this script as the desired user.
+ if [ "X$RUN_AS_USER" != "X" ]
+ then
+ # Resolve the location of the 'id' command
+ IDEXE="/usr/xpg4/bin/id"
+ if [ ! -x $IDEXE ]
+ then
+ IDEXE="/usr/bin/id"
+ if [ ! -x $IDEXE ]
+ then
+ echo "Unable to locate 'id'."
+ echo "Please report this message along with the location of the command on your system."
+ exit 1
+ fi
+ fi
+
+ if [ "`$IDEXE -u -n`" = "$RUN_AS_USER" ]
+ then
+ # Already running as the configured user. Avoid password prompts by not calling su.
+ RUN_AS_USER=""
+ fi
+ fi
+ if [ "X$RUN_AS_USER" != "X" ]
+ then
+ # If LOCKPROP and $RUN_AS_USER are defined then the new user will most likely not be
+ # able to create the lock file. The Wrapper will be able to update this file once it
+ # is created but will not be able to delete it on shutdown. If $2 is defined then
+ # the lock file should be created for the current command
+ if [ "X$LOCKPROP" != "X" ]
+ then
+ if [ "X$2" != "X" ]
+ then
+ # Resolve the primary group
+ RUN_AS_GROUP=`groups $RUN_AS_USER | awk '{print $3}' | tail -1`
+ if [ "X$RUN_AS_GROUP" = "X" ]
+ then
+ RUN_AS_GROUP=$RUN_AS_USER
+ fi
+ touch $LOCKFILE
+ chown $RUN_AS_USER:$RUN_AS_GROUP $LOCKFILE
+ fi
+ fi
+
+ # Still want to change users, recurse. This means that the user will only be
+ # prompted for a password once.
+ su -m $RUN_AS_USER -s /bin/sh -c "$REALPATH $1"
+ RETVAL=$?
+
+ # Now that we are the original user again, we may need to clean up the lock file.
+ if [ "X$LOCKPROP" != "X" ]
+ then
+ getpid
+ if [ "X$pid" = "X" ]
+ then
+ # Wrapper is not running so make sure the lock file is deleted.
+ if [ -f $LOCKFILE ]
+ then
+ rm $LOCKFILE
+ fi
+ fi
+ fi
+
+ exit $RETVAL
+ fi
+}
+
+getpid() {
+ if [ -f $PIDFILE ]
+ then
+ if [ -r $PIDFILE ]
+ then
+ pid=`cat $PIDFILE`
+ if [ "X$pid" != "X" ]
+ then
+ # It is possible that 'a' process with the pid exists but that it is not the
+ # correct process. This can happen in a number of cases, but the most
+ # common is during system startup after an unclean shutdown.
+ # The ps statement below looks for the specific wrapper command running as
+ # the pid. If it is not found then the pid file is considered to be stale.
+ if [ "$DIST_OS" = "solaris" ]
+ then
+ pidtest=`$PSEXE -p $pid -o comm | grep $WRAPPER_CMD | tail -1`
+ else
+ pidtest=`$PSEXE -p $pid -o command | grep $WRAPPER_CMD | tail -1`
+ fi
+ if [ "X$pidtest" = "X" ]
+ then
+ # This is a stale pid file.
+ rm -f $PIDFILE
+ echo "Removed stale pid file: $PIDFILE"
+ pid=""
+ fi
+ fi
+ else
+ echo "Cannot read $PIDFILE."
+ exit 1
+ fi
+ fi
+}
+
+testpid() {
+ pid=`$PSEXE -p $pid | grep $pid | grep -v grep | awk '{print $1}' | tail -1`
+ if [ "X$pid" = "X" ]
+ then
+ # Process is gone so remove the pid file.
+ rm -f $PIDFILE
+ pid=""
+ fi
+}
+
+console() {
+ echo "Running $APP_LONG_NAME..."
+ getpid
+ if [ "X$pid" = "X" ]
+ then
+ COMMAND_LINE="$CMDNICE $WRAPPER_CMD $WRAPPER_CONF wrapper.syslog.ident=$APP_NAME wrapper.pidfile=$PIDFILE $ANCHORPROP $LOCKPROP"
+ exec $COMMAND_LINE
+ else
+ echo "$APP_LONG_NAME is already running."
+ exit 1
+ fi
+}
+
+start() {
+ echo "Starting $APP_LONG_NAME..."
+ getpid
+ if [ "X$pid" = "X" ]
+ then
+ if [ ! -d $DATADIR ]; then
+ mkdir $DATADIR
+ fi
+ if [ ! -d $DATADIR/log ]; then
+ mkdir $DATADIR/log
+ fi
+ COMMAND_LINE="$CMDNICE $WRAPPER_CMD $WRAPPER_CONF wrapper.syslog.ident=$APP_NAME wrapper.pidfile=$PIDFILE wrapper.daemonize=TRUE $ANCHORPROP $IGNOREPROP $LOCKPROP"
+ exec $COMMAND_LINE
+ else
+ echo "$APP_LONG_NAME is already running."
+ exit 1
+ fi
+}
+
+stopit() {
+ echo "Stopping $APP_LONG_NAME..."
+ getpid
+ if [ "X$pid" = "X" ]
+ then
+ echo "$APP_LONG_NAME was not running."
+ else
+ if [ "X$IGNORE_SIGNALS" = "X" ]
+ then
+ # Running so try to stop it.
+ kill $pid
+ if [ $? -ne 0 ]
+ then
+ # An explanation for the failure should have been given
+ echo "Unable to stop $APP_LONG_NAME."
+ exit 1
+ fi
+ else
+ rm -f $ANCHORFILE
+ if [ -f $ANCHORFILE ]
+ then
+ # An explanation for the failure should have been given
+ echo "Unable to stop $APP_LONG_NAME."
+ exit 1
+ fi
+ fi
+
+ # We can not predict how long it will take for the wrapper to
+ # actually stop as it depends on settings in wrapper.conf.
+ # Loop until it does.
+ savepid=$pid
+ CNT=0
+ TOTCNT=0
+ while [ "X$pid" != "X" ]
+ do
+ # Show a waiting message every 5 seconds.
+ if [ "$CNT" -lt "5" ]
+ then
+ CNT=`expr $CNT + 1`
+ else
+ echo "Waiting for $APP_LONG_NAME to exit..."
+ CNT=0
+ fi
+ TOTCNT=`expr $TOTCNT + 1`
+
+ sleep 1
+
+ testpid
+ done
+
+ pid=$savepid
+ testpid
+ if [ "X$pid" != "X" ]
+ then
+ echo "Failed to stop $APP_LONG_NAME."
+ exit 1
+ else
+ echo "Stopped $APP_LONG_NAME."
+ fi
+ fi
+}
+
+status() {
+ getpid
+ if [ "X$pid" = "X" ]
+ then
+ echo "$APP_LONG_NAME is not running."
+ exit 1
+ else
+ echo "$APP_LONG_NAME is running ($pid)."
+ exit 0
+ fi
+}
+
+dump() {
+ echo "Dumping $APP_LONG_NAME..."
+ getpid
+ if [ "X$pid" = "X" ]
+ then
+ echo "$APP_LONG_NAME was not running."
+
+ else
+ kill -3 $pid
+
+ if [ $? -ne 0 ]
+ then
+ echo "Failed to dump $APP_LONG_NAME."
+ exit 1
+ else
+ echo "Dumped $APP_LONG_NAME."
+ fi
+ fi
+}
+
+case "$1" in
+
+ 'console')
+ checkUser $1 touchlock
+ console
+ ;;
+
+ 'start')
+ checkUser $1 touchlock
+ start
+ ;;
+
+ 'stop')
+ checkUser $1
+ stopit
+ ;;
+
+ 'restart')
+ checkUser $1 touchlock
+ stopit
+ start
+ ;;
+
+ 'status')
+ checkUser $1
+ status
+ ;;
+
+ 'dump')
+ checkUser $1
+ dump
+ ;;
+
+ *)
+ echo "Usage: $0 { console | start | stop | restart | status | dump }"
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/tools/package/wrapper/bin/onos-wrapper b/tools/package/wrapper/bin/onos-wrapper
new file mode 100755
index 0000000..3128b95
--- /dev/null
+++ b/tools/package/wrapper/bin/onos-wrapper
Binary files differ
diff --git a/tools/package/wrapper/etc/onos-wrapper.conf b/tools/package/wrapper/etc/onos-wrapper.conf
new file mode 100644
index 0000000..6c6777b
--- /dev/null
+++ b/tools/package/wrapper/etc/onos-wrapper.conf
@@ -0,0 +1,135 @@
+# ------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ------------------------------------------------------------------------
+
+#********************************************************************
+# Wrapper Properties
+#********************************************************************
+set.default.JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64/
+set.default.KARAF_HOME=/opt/onos/apache-karaf-3.0.1
+set.default.KARAF_BASE=/opt/onos/apache-karaf-3.0.1
+set.default.KARAF_DATA=/opt/onos/apache-karaf-3.0.1/data
+set.default.KARAF_ETC=/opt/onos/apache-karaf-3.0.1/etc
+
+# Java Application
+wrapper.working.dir=%KARAF_BASE%
+wrapper.java.command=%JAVA_HOME%/bin/java
+wrapper.java.mainclass=org.apache.karaf.wrapper.internal.Main
+wrapper.java.classpath.1=%KARAF_HOME%/lib/karaf-wrapper.jar
+wrapper.java.classpath.2=%KARAF_HOME%/lib/karaf.jar
+wrapper.java.classpath.3=%KARAF_HOME%/lib/karaf-jmx-boot.jar
+wrapper.java.classpath.4=%KARAF_HOME%/lib/karaf-jaas-boot.jar
+wrapper.java.classpath.5=%KARAF_HOME%/lib/karaf-wrapper-main.jar
+wrapper.java.classpath.6=%KARAF_HOME%/lib/karaf-org.osgi.core.jar
+wrapper.java.library.path.1=%KARAF_HOME%/lib/
+
+# Application Parameters. Add parameters as needed starting from 1
+#wrapper.app.parameter.1=
+
+# JVM Parameters
+# note that n is the parameter number starting from 1.
+wrapper.java.additional.1=-Dkaraf.home=%KARAF_HOME%
+wrapper.java.additional.2=-Dkaraf.base=%KARAF_BASE%
+wrapper.java.additional.3=-Dkaraf.data=%KARAF_DATA%
+wrapper.java.additional.4=-Dkaraf.etc=%KARAF_ETC%
+wrapper.java.additional.5=-Dcom.sun.management.jmxremote
+wrapper.java.additional.6=-Djavax.management.builder.initial=org.apache.karaf.management.boot.KarafMBeanServerBuilder
+wrapper.java.additional.7=-Dkaraf.startLocalConsole=false
+wrapper.java.additional.8=-Dkaraf.startRemoteShell=true
+wrapper.java.additional.9=-Djava.endorsed.dirs=%JAVA_HOME%/jre/lib/endorsed:%JAVA_HOME%/lib/endorsed:%KARAF_HOME%/lib/endorsed
+wrapper.java.additional.10=-Djava.ext.dirs=%JAVA_HOME%/jre/lib/ext:%JAVA_HOME%/lib/ext:%KARAF_HOME%/lib/ext
+
+# Uncomment to enable jmx
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.port=1616
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.authenticate=false
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.ssl=false
+
+# Uncomment to enable YourKit profiling
+#wrapper.java.additional.n=-Xrunyjpagent
+
+# Uncomment to enable remote debugging
+#wrapper.java.additional.n=-Xdebug -Xnoagent -Djava.compiler=NONE
+#wrapper.java.additional.n=-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
+
+# Initial Java Heap Size (in MB)
+#wrapper.java.initmemory=3
+
+# Maximum Java Heap Size (in MB)
+wrapper.java.maxmemory=512
+
+
+#********************************************************************
+# Wrapper Logging Properties
+#********************************************************************
+# Format of output for the console. (See docs for formats)
+wrapper.console.format=PM
+
+# Log Level for console output. (See docs for log levels)
+wrapper.console.loglevel=INFO
+
+# Log file to use for wrapper output logging.
+wrapper.logfile=%KARAF_DATA%/log/wrapper.log
+
+# Format of output for the log file. (See docs for formats)
+wrapper.logfile.format=LPTM
+
+# Log Level for log file output. (See docs for log levels)
+wrapper.logfile.loglevel=INFO
+
+# Maximum size that the log file will be allowed to grow to before
+# the log is rolled. Size is specified in bytes. The default value
+# of 0, disables log rolling. May abbreviate with the 'k' (kb) or
+# 'm' (mb) suffix. For example: 10m = 10 megabytes.
+wrapper.logfile.maxsize=10m
+
+# Maximum number of rolled log files which will be allowed before old
+# files are deleted. The default value of 0 implies no limit.
+wrapper.logfile.maxfiles=5
+
+# Log Level for sys/event log output. (See docs for log levels)
+wrapper.syslog.loglevel=NONE
+
+#********************************************************************
+# Wrapper Windows Properties
+#********************************************************************
+# Title to use when running as a console
+wrapper.console.title=onos
+
+#********************************************************************
+# Wrapper Windows NT/2000/XP Service Properties
+#********************************************************************
+# WARNING - Do not modify any of these properties when an application
+# using this configuration file has been installed as a service.
+# Please uninstall the service before modifying this section. The
+# service can then be reinstalled.
+
+# Name of the service
+wrapper.ntservice.name=onos
+
+# Display name of the service
+wrapper.ntservice.displayname=onos
+
+# Description of the service
+wrapper.ntservice.description=ONOS
+
+# Service dependencies. Add dependencies as needed starting from 1
+wrapper.ntservice.dependency.1=
+
+# Mode in which the service is installed. AUTO_START or DEMAND_START
+wrapper.ntservice.starttype=AUTO_START
+
+# Allow the service to interact with the desktop.
+wrapper.ntservice.interactive=false
diff --git a/tools/package/wrapper/lib/karaf-wrapper.jar b/tools/package/wrapper/lib/karaf-wrapper.jar
new file mode 100644
index 0000000..4db355b
--- /dev/null
+++ b/tools/package/wrapper/lib/karaf-wrapper.jar
Binary files differ
diff --git a/tools/package/wrapper/lib/libwrapper.so b/tools/package/wrapper/lib/libwrapper.so
new file mode 100644
index 0000000..24197bf
--- /dev/null
+++ b/tools/package/wrapper/lib/libwrapper.so
Binary files differ
diff --git a/tools/test/README b/tools/test/README
new file mode 100644
index 0000000..3d6b1eb
--- /dev/null
+++ b/tools/test/README
@@ -0,0 +1 @@
+Artifacts for system testing onos.
diff --git a/tools/test/bin/onos-install b/tools/test/bin/onos-install
new file mode 100755
index 0000000..babfdef
--- /dev/null
+++ b/tools/test/bin/onos-install
@@ -0,0 +1,24 @@
+#!/bin/bash
+#-------------------------------------------------------------------------------
+# Remotely pushes bits to a remote machine and install & starts ONOS.
+#-------------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+# If the first option is -f attempt uninstall first.
+[ "$1" = "-f" ] && shift && onos-uninstall ${1:-$OCI}
+
+remote=$ONOS_USER@${1:-$OCI}
+
+scp -q $ONOS_TAR $remote:/tmp
+
+ssh $remote "
+ [ -d $ONOS_INSTALL_DIR/bin ] && echo \"ONOS is already installed\" && exit 1
+
+ sudo mkdir -p $ONOS_INSTALL_DIR && sudo chown sdn:sdn $ONOS_INSTALL_DIR
+ tar zxmf /tmp/$ONOS_BITS.tar.gz -C $ONOS_INSTALL_DIR --strip-components=1
+
+ ln -s /opt/onos/$KARAF_DIST/data/log /opt/onos/log
+
+"
diff --git a/tools/test/bin/onos-uninstall b/tools/test/bin/onos-uninstall
new file mode 100755
index 0000000..a535c0a
--- /dev/null
+++ b/tools/test/bin/onos-uninstall
@@ -0,0 +1,15 @@
+#!/bin/bash
+#-------------------------------------------------------------------------------
+# Remotely stops & uninstalls ONOS.
+#-------------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+remote=$ONOS_USER@${1:-$OCI}
+
+ssh $remote "
+ [ -f $ONOS_INSTALL_DIR/bin/onos ] && \
+ $ONOS_INSTALL_DIR/bin/onos halt 2>/dev/null
+ sudo rm -fr $ONOS_INSTALL_DIR
+"
diff --git a/utils/misc/src/main/java/org/onlab/packet/IpAddress.java b/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
index 02ed37a..a10e710 100644
--- a/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
+++ b/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
@@ -18,6 +18,7 @@
//maximum CIDR value
public static final int MAX_INET_MASK = 32;
+ //no mask (no network), e.g. a simple address
public static final int DEFAULT_MASK = 0;
/**
@@ -112,7 +113,7 @@
final String [] parts = address.split("\\/");
if (parts.length > 2) {
throw new IllegalArgumentException("Malformed IP address string; "
- + "Addres must take form \"x.x.x.x\" or \"x.x.x.x/y\"");
+ + "Address must take form \"x.x.x.x\" or \"x.x.x.x/y\"");
}
int mask = DEFAULT_MASK;
@@ -128,7 +129,7 @@
final String [] net = parts[0].split("\\.");
if (net.length != INET_LEN) {
throw new IllegalArgumentException("Malformed IP address string; "
- + "Addres must have four decimal values separated by dots (.)");
+ + "Address must have four decimal values separated by dots (.)");
}
final byte [] bytes = new byte[INET_LEN];
for (int i = 0; i < INET_LEN; i++) {