Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
Conflicts:
apps/optical/src/main/java/org/onlab/onos/optical/cfg/OpticalConfigProvider.java
diff --git a/core/api/src/main/java/org/onlab/onos/net/device/DeviceProvider.java b/core/api/src/main/java/org/onlab/onos/net/device/DeviceProvider.java
index 9934b8d..ec73ce5 100644
--- a/core/api/src/main/java/org/onlab/onos/net/device/DeviceProvider.java
+++ b/core/api/src/main/java/org/onlab/onos/net/device/DeviceProvider.java
@@ -13,7 +13,7 @@
/**
* Triggers an asynchronous probe of the specified device, intended to
- * determine whether the host is present or not. An indirect result of this
+ * determine whether the device is present or not. An indirect result of this
* should be invocation of
* {@link org.onlab.onos.net.device.DeviceProviderService#deviceConnected} )} or
* {@link org.onlab.onos.net.device.DeviceProviderService#deviceDisconnected}
diff --git a/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java b/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
index fd47dc7..a157e50 100644
--- a/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
@@ -161,6 +161,17 @@
}
}
+ // Queries a device for port information.
+ private void queryPortInfo(DeviceId deviceId) {
+ Device device = store.getDevice(deviceId);
+ // FIXME: Device might not be there yet. (eventual consistent)
+ if (device == null) {
+ return;
+ }
+ DeviceProvider provider = getProvider(device.providerId());
+ provider.triggerProbe(device);
+ }
+
@Override
public void removeDevice(DeviceId deviceId) {
checkNotNull(deviceId, DEVICE_ID_NULL);
@@ -210,8 +221,6 @@
log.info("Device {} connected", deviceId);
// check my Role
MastershipRole role = mastershipService.requestRoleFor(deviceId);
- log.info("## - our role for {} is {} [master is {}]", deviceId, role,
- mastershipService.getMasterFor(deviceId));
if (role != MastershipRole.MASTER) {
// TODO: Do we need to explicitly tell the Provider that
// this instance is no longer the MASTER? probably not
@@ -265,7 +274,6 @@
// but if I was the last STANDBY connection, etc. and no one else
// was there to mark the device offline, this instance may need to
// temporarily request for Master Role and mark offline.
- log.info("## for {} role is {}", deviceId, mastershipService.getLocalRole(deviceId));
if (!mastershipService.getLocalRole(deviceId).equals(MastershipRole.MASTER)) {
log.debug("Device {} disconnected, but I am not the master", deviceId);
//let go of ability to be backup
@@ -373,7 +381,6 @@
final DeviceId did = event.subject();
final NodeId myNodeId = clusterService.getLocalNode().id();
- log.info("## got Mastershipevent for dev {}", did);
if (myNodeId.equals(event.roleInfo().master())) {
MastershipTerm term = termService.getMastershipTerm(did);
@@ -384,7 +391,6 @@
return;
}
- log.info("## setting term for CPS as new master for {}", did);
// only set the new term if I am the master
deviceClockProviderService.setMastershipTerm(did, term);
@@ -404,6 +410,7 @@
device.serialNumber(), device.chassisId()));
}
//TODO re-collect device information to fix potential staleness
+ queryPortInfo(did);
applyRole(did, MastershipRole.MASTER);
} else if (event.roleInfo().backups().contains(myNodeId)) {
applyRole(did, MastershipRole.STANDBY);
diff --git a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
index 67e0867..01514d4 100644
--- a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
@@ -299,7 +299,8 @@
private void extraneousFlow(FlowRule flowRule) {
checkNotNull(flowRule, FLOW_RULE_NULL);
checkValidity();
- removeFlowRules(flowRule);
+ FlowRuleProvider frp = getProvider(flowRule.deviceId());
+ frp.removeFlowRule(flowRule);
log.debug("Flow {} is on switch but not in store.", flowRule);
}
diff --git a/core/net/src/main/java/org/onlab/onos/net/statistic/impl/StatisticManager.java b/core/net/src/main/java/org/onlab/onos/net/statistic/impl/StatisticManager.java
index 4bca215..9b1a2e0 100644
--- a/core/net/src/main/java/org/onlab/onos/net/statistic/impl/StatisticManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/statistic/impl/StatisticManager.java
@@ -9,6 +9,7 @@
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.Path;
+
import org.onlab.onos.net.flow.FlowRule;
import org.onlab.onos.net.flow.FlowRuleEvent;
import org.onlab.onos.net.flow.FlowRuleListener;
@@ -35,12 +36,14 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StatisticStore statisticStore;
+
private final InternalFlowRuleListener listener = new InternalFlowRuleListener();
@Activate
public void activate() {
flowRuleService.addListener(listener);
log.info("Started");
+
}
@Deactivate
@@ -81,7 +84,22 @@
@Override
public void event(FlowRuleEvent event) {
-
+// FlowRule rule = event.subject();
+// switch (event.type()) {
+// case RULE_ADDED:
+// case RULE_UPDATED:
+// if (rule instanceof FlowEntry) {
+// statisticStore.addOrUpdateStatistic((FlowEntry) rule);
+// }
+// break;
+// case RULE_ADD_REQUESTED:
+// statisticStore.prepareForStatistics(rule);
+// break;
+// case RULE_REMOVE_REQUESTED:
+// case RULE_REMOVED:
+// statisticStore.removeFromStatistics(rule);
+// break;
+// }
}
}
diff --git a/core/net/src/test/java/org/onlab/onos/event/impl/TestEventDispatcher.java b/core/net/src/test/java/org/onlab/onos/event/impl/TestEventDispatcher.java
index 9eb3980..d2cbc24 100644
--- a/core/net/src/test/java/org/onlab/onos/event/impl/TestEventDispatcher.java
+++ b/core/net/src/test/java/org/onlab/onos/event/impl/TestEventDispatcher.java
@@ -15,6 +15,7 @@
implements EventDeliveryService {
@Override
+ @SuppressWarnings("unchecked")
public void post(Event event) {
EventSink sink = getSink(event.getClass());
checkState(sink != null, "No sink for event %s", event);
diff --git a/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java b/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
index ca7cc07..2a7384b 100644
--- a/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
+++ b/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
@@ -1,15 +1,5 @@
package org.onlab.onos.net.flow.impl;
-import static java.util.Collections.EMPTY_LIST;
-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 static org.junit.Assert.fail;
-import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
-import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
-import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -65,6 +55,16 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+import static java.util.Collections.EMPTY_LIST;
+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 static org.junit.Assert.fail;
+import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
+import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
+import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
+
/**
* Test codifying the flow rule service & flow rule provider service contracts.
*/
@@ -176,6 +176,7 @@
// TODO: If preserving iteration order is a requirement, redo FlowRuleStore.
//backing store is sensitive to the order of additions/removals
+ @SuppressWarnings("unchecked")
private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
Iterable<FlowEntry> rules = service.getFlowEntries(DID);
@@ -539,6 +540,7 @@
}
@Override
+ @SuppressWarnings("unchecked")
public CompletedBatchOperation get()
throws InterruptedException, ExecutionException {
return new CompletedBatchOperation(true, EMPTY_LIST);
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InternalDeviceEventSerializer.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InternalDeviceEventSerializer.java
index 5f97afd..c789c96 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InternalDeviceEventSerializer.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InternalDeviceEventSerializer.java
@@ -35,6 +35,8 @@
Class<InternalDeviceEvent> type) {
ProviderId providerId = (ProviderId) kryo.readClassAndObject(input);
DeviceId deviceId = (DeviceId) kryo.readClassAndObject(input);
+
+ @SuppressWarnings("unchecked")
Timestamped<DeviceDescription> deviceDescription
= (Timestamped<DeviceDescription>) kryo.readClassAndObject(input);
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InternalPortEventSerializer.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InternalPortEventSerializer.java
index 4f4a9e6..2facb7e 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InternalPortEventSerializer.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InternalPortEventSerializer.java
@@ -37,6 +37,8 @@
Class<InternalPortEvent> type) {
ProviderId providerId = (ProviderId) kryo.readClassAndObject(input);
DeviceId deviceId = (DeviceId) kryo.readClassAndObject(input);
+
+ @SuppressWarnings("unchecked")
Timestamped<List<PortDescription>> portDescriptions
= (Timestamped<List<PortDescription>>) kryo.readClassAndObject(input);
diff --git a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleFlowRuleStore.java b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleFlowRuleStore.java
index a96cacb..d312af5 100644
--- a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleFlowRuleStore.java
+++ b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleFlowRuleStore.java
@@ -177,6 +177,7 @@
public boolean deleteFlowRule(FlowRule rule) {
List<StoredFlowEntry> entries = getFlowEntries(rule.deviceId(), rule.id());
+
synchronized (entries) {
for (StoredFlowEntry entry : entries) {
if (entry.equals(rule)) {
diff --git a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleIntentStore.java b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleIntentStore.java
index 0ec8612..12e62e2 100644
--- a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleIntentStore.java
+++ b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleIntentStore.java
@@ -82,12 +82,28 @@
public IntentEvent setState(Intent intent, IntentState state) {
IntentId id = intent.id();
states.put(id, state);
- IntentEvent.Type type = (state == SUBMITTED ? IntentEvent.Type.SUBMITTED :
- (state == INSTALLED ? IntentEvent.Type.INSTALLED :
- (state == FAILED ? IntentEvent.Type.FAILED :
- state == WITHDRAWN ? IntentEvent.Type.WITHDRAWN :
- null)));
- return type == null ? null : new IntentEvent(type, intent);
+ IntentEvent.Type type = null;
+
+ switch (state) {
+ case SUBMITTED:
+ type = IntentEvent.Type.SUBMITTED;
+ break;
+ case INSTALLED:
+ type = IntentEvent.Type.INSTALLED;
+ break;
+ case FAILED:
+ type = IntentEvent.Type.FAILED;
+ break;
+ case WITHDRAWN:
+ type = IntentEvent.Type.WITHDRAWN;
+ break;
+ default:
+ break;
+ }
+ if (type == null) {
+ return null;
+ }
+ return new IntentEvent(type, intent);
}
@Override
diff --git a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitch.java b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitch.java
index 6fd02bc..1375a20 100644
--- a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitch.java
+++ b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitch.java
@@ -110,8 +110,7 @@
*
* @param role the failed role
*/
- void returnRoleAssertFailure(RoleState role);
-
+ public void returnRoleAssertFailure(RoleState role);
/**
* Indicates if this switch is optical.
@@ -120,5 +119,4 @@
*/
public boolean isOptical();
-
}
diff --git a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitchListener.java b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitchListener.java
index 53217da..33e5bdf 100644
--- a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitchListener.java
+++ b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitchListener.java
@@ -20,6 +20,12 @@
public void switchRemoved(Dpid dpid);
/**
+ * Notify that the switch has changed in some way.
+ * @param dpid the switch that changed
+ */
+ public void switchChanged(Dpid dpid);
+
+ /**
* Notify that a port has changed.
* @param dpid the switch on which the change happened.
* @param status the new state of the port.
diff --git a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java
index 009cd3f..5047867 100644
--- a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java
+++ b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java
@@ -565,6 +565,9 @@
@Override
void processOFStatisticsReply(OFChannelHandler h,
OFStatsReply m) {
+ if (m.getStatsType().equals(OFStatsType.PORT_DESC)) {
+ h.sw.setPortDescReply((OFPortDescStatsReply) m);
+ }
h.dispatchMessage(m);
}
@@ -608,6 +611,12 @@
h.dispatchMessage(m);
}
+ @Override
+ void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) {
+ h.sw.setFeaturesReply(m);
+ h.dispatchMessage(m);
+ }
+
};
private final boolean handshakeComplete;
diff --git a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java
index 565ccb9..cd9b760 100644
--- a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java
+++ b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java
@@ -27,6 +27,8 @@
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPacketIn;
import org.projectfloodlight.openflow.protocol.OFPortStatus;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -146,6 +148,11 @@
l.portChanged(dpid, (OFPortStatus) msg);
}
break;
+ case FEATURES_REPLY:
+ for (OpenFlowSwitchListener l : ofSwitchListener) {
+ l.switchChanged(dpid);
+ }
+ break;
case PACKET_IN:
OpenFlowPacketContext pktCtx = DefaultOpenFlowPacketContext
.packetContextFromPacketIn(this.getSwitch(dpid),
@@ -154,9 +161,15 @@
p.handlePacket(pktCtx);
}
break;
+ case STATS_REPLY:
+ OFStatsReply reply = (OFStatsReply) msg;
+ if (reply.getStatsType().equals(OFStatsType.PORT_DESC)) {
+ for (OpenFlowSwitchListener l : ofSwitchListener) {
+ l.switchChanged(dpid);
+ }
+ }
case FLOW_REMOVED:
case ERROR:
- case STATS_REPLY:
case BARRIER_REPLY:
executor.submit(new OFMessageHandler(dpid, msg));
break;
diff --git a/providers/lldp/src/main/java/org/onlab/onos/provider/lldp/impl/LinkDiscovery.java b/providers/lldp/src/main/java/org/onlab/onos/provider/lldp/impl/LinkDiscovery.java
index 75ce1da..95cd619 100644
--- a/providers/lldp/src/main/java/org/onlab/onos/provider/lldp/impl/LinkDiscovery.java
+++ b/providers/lldp/src/main/java/org/onlab/onos/provider/lldp/impl/LinkDiscovery.java
@@ -344,7 +344,8 @@
}
private void sendProbes(Long portNumber) {
- if (mastershipService.getLocalRole(this.device.id()) ==
+ if (device.type() != Device.Type.ROADM &&
+ mastershipService.getLocalRole(this.device.id()) ==
MastershipRole.MASTER) {
OutboundPacket pkt = this.createOutBoundLLDP(portNumber);
pktService.emit(pkt);
diff --git a/providers/openflow/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java b/providers/openflow/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java
index fcc7810..984e8ae 100644
--- a/providers/openflow/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java
+++ b/providers/openflow/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java
@@ -23,7 +23,9 @@
import org.onlab.onos.openflow.controller.OpenFlowSwitch;
import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
import org.onlab.onos.openflow.controller.RoleState;
+import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriver;
import org.onlab.packet.ChassisId;
+import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFPortConfig;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortState;
@@ -89,6 +91,28 @@
@Override
public void triggerProbe(Device device) {
LOG.info("Triggering probe on device {}", device.id());
+
+ // 1. check device liveness
+ // FIXME if possible, we might want this to be part of
+ // OpenFlowSwitch interface so the driver interface isn't misused.
+ OpenFlowSwitch sw = controller.getSwitch(dpid(device.id().uri()));
+ if (!((OpenFlowSwitchDriver) sw).isConnected()) {
+ providerService.deviceDisconnected(device.id());
+ return;
+ }
+
+ // 2. Prompt an update of port information. Do we have an XID for this?
+ OFFactory fact = sw.factory();
+ switch (fact.getVersion()) {
+ case OF_10:
+ sw.sendMsg(fact.buildFeaturesRequest().setXid(0).build());
+ break;
+ case OF_13:
+ sw.sendMsg(fact.buildPortDescStatsRequest().setXid(0).build());
+ break;
+ default:
+ LOG.warn("Unhandled protocol version");
+ }
}
@Override
@@ -141,6 +165,17 @@
providerService.deviceDisconnected(deviceId(uri(dpid)));
}
+
+ @Override
+ public void switchChanged(Dpid dpid) {
+ if (providerService == null) {
+ return;
+ }
+ DeviceId did = deviceId(uri(dpid));
+ OpenFlowSwitch sw = controller.getSwitch(dpid);
+ providerService.updatePorts(did, buildPortDescriptions(sw.getPorts()));
+ }
+
@Override
public void portChanged(Dpid dpid, OFPortStatus status) {
PortDescription portDescription = buildPortDescription(status.getDesc());
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
index 54265ba..d18a72f 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -233,6 +233,10 @@
}
@Override
+ public void switchChanged(Dpid dpid) {
+ }
+
+ @Override
public void portChanged(Dpid dpid, OFPortStatus status) {
//TODO: Decide whether to evict flows internal store.
}
@@ -313,6 +317,7 @@
}
return false;
}
+
}
private class InstallationFuture implements Future<CompletedBatchOperation> {
diff --git a/providers/openflow/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java b/providers/openflow/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
index 7f16eaa..c3f5a68 100644
--- a/providers/openflow/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
+++ b/providers/openflow/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
@@ -118,6 +118,12 @@
DeviceId.deviceId("of:" + Long.toHexString(dpid.value())));
}
+
+ @Override
+ public void switchChanged(Dpid dpid) {
+ //might not need to do anything since DeviceManager is notified
+ }
+
@Override
public void portChanged(Dpid dpid, OFPortStatus status) {
LinkDiscovery ld = discoverers.get(dpid);
diff --git a/utils/osgi/src/main/java/org/onlab/osgi/TestServiceDirectory.java b/utils/osgi/src/main/java/org/onlab/osgi/TestServiceDirectory.java
index 2915d4b..7fecbc3 100644
--- a/utils/osgi/src/main/java/org/onlab/osgi/TestServiceDirectory.java
+++ b/utils/osgi/src/main/java/org/onlab/osgi/TestServiceDirectory.java
@@ -6,6 +6,7 @@
/**
* Service directory implementation suitable for testing.
*/
+@SuppressWarnings("unchecked")
public class TestServiceDirectory implements ServiceDirectory {
private ClassToInstanceMap<Object> services = MutableClassToInstanceMap.create();
diff --git a/web/gui/src/main/webapp/index.html b/web/gui/src/main/webapp/index.html
index 3b0d290..c2cb8f8 100644
--- a/web/gui/src/main/webapp/index.html
+++ b/web/gui/src/main/webapp/index.html
@@ -32,20 +32,20 @@
<div id="view"></div>
</div>
- // Initialize the UI...
+ <!-- Initialize the UI...-->
<script type="text/javascript">
var ONOS = $.onos({note: "config, if needed"});
</script>
- // include module files
- // + mast.js
- // + nav.js
- // + .... application views
+ <!-- include module files-->
+ <!-- + mast.js-->
+ <!-- + nav.js-->
+ <!-- + .... application views-->
- // for now, we are just bootstrapping the network visualization
+ <!-- for now, we are just bootstrapping the network visualization-->
<script src="network.js" type="text/javascript"></script>
- // finally, build the UI
+ <!-- finally, build the UI-->
<script type="text/javascript">
$(ONOS.buildUi);
</script>
diff --git a/web/gui/src/main/webapp/network.js b/web/gui/src/main/webapp/network.js
index 81105dc..d7261de 100644
--- a/web/gui/src/main/webapp/network.js
+++ b/web/gui/src/main/webapp/network.js
@@ -100,7 +100,7 @@
network.data.nodes.forEach(function(n) {
var ypc = yPosConstraintForNode(n),
- ix = Math.random() * 0.8 * nw + 0.1 * nw,
+ ix = Math.random() * 0.6 * nw + 0.2 * nw,
iy = ypc * nh,
node = {
id: n.id,
@@ -152,11 +152,49 @@
.attr('width', view.width)
.attr('height', view.height)
.append('g')
- .attr('transform', config.force.translate());
+// .attr('id', 'zoomable')
+ .attr('transform', config.force.translate())
+// .call(d3.behavior.zoom().on("zoom", zoomRedraw));
- // TODO: svg.append('defs')
- // TODO: glow/blur stuff
+// function zoomRedraw() {
+// d3.select("#zoomable").attr("transform",
+// "translate(" + d3.event.translate + ")"
+// + " scale(" + d3.event.scale + ")");
+// }
+
+ // TODO: svg.append('defs') for markers?
+
+ // TODO: move glow/blur stuff to util script
+ var glow = network.svg.append('filter')
+ .attr('x', '-50%')
+ .attr('y', '-50%')
+ .attr('width', '200%')
+ .attr('height', '200%')
+ .attr('id', 'blue-glow');
+
+ glow.append('feColorMatrix')
+ .attr('type', 'matrix')
+ .attr('values', '0 0 0 0 0 ' +
+ '0 0 0 0 0 ' +
+ '0 0 0 0 .7 ' +
+ '0 0 0 1 0 ');
+
+ glow.append('feGaussianBlur')
+ .attr('stdDeviation', 3)
+ .attr('result', 'coloredBlur');
+
+ glow.append('feMerge').selectAll('feMergeNode')
+ .data(['coloredBlur', 'SourceGraphic'])
+ .enter().append('feMergeNode')
+ .attr('in', String);
+
// TODO: legend (and auto adjust on scroll)
+// $('#view').on('scroll', function() {
+//
+// });
+
+
+
network.link = network.svg.append('g').selectAll('.link')
.data(network.force.links(), function(d) {return d.id})
@@ -164,27 +202,90 @@
.attr('class', 'link');
// TODO: drag behavior
- // TODO: closest node deselect
+ network.draggedThreshold = d3.scale.linear()
+ .domain([0, 0.1])
+ .range([5, 20])
+ .clamp(true);
+
+ function dragged(d) {
+ var threshold = network.draggedThreshold(network.force.alpha()),
+ dx = d.oldX - d.px,
+ dy = d.oldY - d.py;
+ if (Math.abs(dx) >= threshold || Math.abs(dy) >= threshold) {
+ d.dragged = true;
+ }
+ return d.dragged;
+ }
+
+ network.drag = d3.behavior.drag()
+ .origin(function(d) { return d; })
+ .on('dragstart', function(d) {
+ d.oldX = d.x;
+ d.oldY = d.y;
+ d.dragged = false;
+ d.fixed |= 2;
+ })
+ .on('drag', function(d) {
+ d.px = d3.event.x;
+ d.py = d3.event.y;
+ if (dragged(d)) {
+ if (!network.force.alpha()) {
+ network.force.alpha(.025);
+ }
+ }
+ })
+ .on('dragend', function(d) {
+ if (!dragged(d)) {
+ selectObject(d, this);
+ }
+ d.fixed &= ~6;
+ });
+
+ $('#view').on('click', function(e) {
+ if (!$(e.target).closest('.node').length) {
+ deselectObject();
+ }
+ });
// TODO: add drag, mouseover, mouseout behaviors
network.node = network.svg.selectAll('.node')
.data(network.force.nodes(), function(d) {return d.id})
.enter().append('g')
- .attr('class', 'node')
+ .attr('class', function(d) {
+ return 'node ' + d.type;
+ })
.attr('transform', function(d) {
return translate(d.x, d.y);
})
- // .call(network.drag)
- .on('mouseover', function(d) {})
- .on('mouseout', function(d) {});
+ .call(network.drag)
+ .on('mouseover', function(d) {
+ if (!selected.obj) {
+ if (network.mouseoutTimeout) {
+ clearTimeout(network.mouseoutTimeout);
+ network.mouseoutTimeout = null;
+ }
+ highlightObject(d);
+ }
+ })
+ .on('mouseout', function(d) {
+ if (!selected.obj) {
+ if (network.mouseoutTimeout) {
+ clearTimeout(network.mouseoutTimeout);
+ network.mouseoutTimeout = null;
+ }
+ network.mouseoutTimeout = setTimeout(function() {
+ highlightObject(null);
+ }, 160);
+ }
+ });
// TODO: augment stroke and fill functions
network.nodeRect = network.node.append('rect')
// TODO: css for node rects
.attr('rx', 5)
.attr('ry', 5)
- .attr('stroke', function(d) { return '#000'})
- .attr('fill', function(d) { return '#ddf'})
+// .attr('stroke', function(d) { return '#000'})
+// .attr('fill', function(d) { return '#ddf'})
.attr('width', 60)
.attr('height', 24);
diff --git a/web/gui/src/main/webapp/onos.css b/web/gui/src/main/webapp/onos.css
index 328e109..548ca57 100644
--- a/web/gui/src/main/webapp/onos.css
+++ b/web/gui/src/main/webapp/onos.css
@@ -13,7 +13,7 @@
*/
span.title {
- color: red;
+ color: darkblue;
font-size: 16pt;
font-style: italic;
}
@@ -30,7 +30,7 @@
* === DEBUGGING ======
*/
svg {
- border: 1px dashed red;
+ /*border: 1px dashed red;*/
}
@@ -64,36 +64,45 @@
-moz-transition: opacity 250ms;
}
-.node text {
- fill: #000;
+/*differentiate between packet and optical nodes*/
+svg .node.pkt rect {
+ fill: #77a;
+}
+
+svg .node.opt rect {
+ fill: #7a7;
+}
+
+svg .node text {
+ fill: white;
font: 10px sans-serif;
pointer-events: none;
}
-.node.selected rect {
+svg .node.selected rect {
filter: url(#blue-glow);
}
-.link.inactive,
-.node.inactive rect,
-.node.inactive text {
+svg .link.inactive,
+svg .node.inactive rect,
+svg .node.inactive text {
opacity: .2;
}
-.node.inactive.selected rect,
-.node.inactive.selected text {
+svg .node.inactive.selected rect,
+svg .node.inactive.selected text {
opacity: .6;
}
-.legend {
+svg .legend {
position: fixed;
}
-.legend .category rect {
+svg .legend .category rect {
stroke-width: 1px;
}
-.legend .category text {
+svg .legend .category text {
fill: #000;
font: 10px sans-serif;
pointer-events: none;
@@ -110,15 +119,15 @@
#frame {
width: 100%;
height: 100%;
- background-color: #ffd;
+ background-color: #cdf;
}
#mast {
height: 32px;
- background-color: #dda;
+ background-color: #abe;
vertical-align: baseline;
}
#main {
- background-color: #99b;
+ background-color: #99c;
}