Toggle navigation
Toggle navigation
This project
Loading...
Sign in
홍길동
/
onos
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
Thomas Vachuska
2014-11-09 08:26:47 -0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
690e5f62865c733122764f32a5b4238efd2c6842
690e5f62
1 parent
e4adf249
Adding GUI server-side code.
Change-Id: Iaa8452a315762f9a57c5bdaec2de4ec60877d928
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
314 additions
and
97 deletions
web/gui/src/main/java/org/onlab/onos/gui/TopologyWebSocket.java
web/gui/src/main/java/org/onlab/onos/gui/TopologyWebSocket.java
View file @
690e5f6
...
...
@@ -20,30 +20,40 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import
com.fasterxml.jackson.databind.node.ArrayNode
;
import
com.fasterxml.jackson.databind.node.ObjectNode
;
import
org.eclipse.jetty.websocket.WebSocket
;
import
org.onlab.onos.event.Event
;
import
org.onlab.onos.mastership.MastershipEvent
;
import
org.onlab.onos.mastership.MastershipListener
;
import
org.onlab.onos.mastership.MastershipService
;
import
org.onlab.onos.net.Annotations
;
import
org.onlab.onos.net.Device
;
import
org.onlab.onos.net.DeviceId
;
import
org.onlab.onos.net.Host
;
import
org.onlab.onos.net.HostId
;
import
org.onlab.onos.net.HostLocation
;
import
org.onlab.onos.net.Link
;
import
org.onlab.onos.net.Path
;
import
org.onlab.onos.net.device.DeviceEvent
;
import
org.onlab.onos.net.device.DeviceListener
;
import
org.onlab.onos.net.device.DeviceService
;
import
org.onlab.onos.net.host.HostEvent
;
import
org.onlab.onos.net.host.HostListener
;
import
org.onlab.onos.net.host.HostService
;
import
org.onlab.onos.net.intent.IntentId
;
import
org.onlab.onos.net.link.LinkEvent
;
import
org.onlab.onos.net.topology.Topology
;
import
org.onlab.onos.net.topology.TopologyEdge
;
import
org.onlab.onos.net.topology.TopologyEvent
;
import
org.onlab.onos.net.topology.TopologyGraph
;
import
org.onlab.onos.net.topology.TopologyListener
;
import
org.onlab.onos.net.topology.TopologyService
;
import
org.onlab.onos.net.topology.TopologyVertex
;
import
org.onlab.onos.net.link.LinkListener
;
import
org.onlab.onos.net.link.LinkService
;
import
org.onlab.onos.net.topology.PathService
;
import
org.onlab.osgi.ServiceDirectory
;
import
org.onlab.packet.IpAddress
;
import
java.io.IOException
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.Map
;
import
java.util.Set
;
import
static
com
.
google
.
common
.
base
.
Preconditions
.
checkNotNull
;
import
static
org
.
onlab
.
onos
.
net
.
DeviceId
.
deviceId
;
import
static
org
.
onlab
.
onos
.
net
.
HostId
.
hostId
;
import
static
org
.
onlab
.
onos
.
net
.
device
.
DeviceEvent
.
Type
.
DEVICE_ADDED
;
import
static
org
.
onlab
.
onos
.
net
.
device
.
DeviceEvent
.
Type
.
DEVICE_REMOVED
;
import
static
org
.
onlab
.
onos
.
net
.
link
.
LinkEvent
.
Type
.
LINK_ADDED
;
...
...
@@ -52,16 +62,24 @@ import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED;
/**
* Web socket capable of interacting with the GUI topology view.
*/
public
class
TopologyWebSocket
implements
WebSocket
.
OnTextMessage
,
TopologyListener
{
public
class
TopologyWebSocket
implements
WebSocket
.
OnTextMessage
{
private
final
ServiceDirectory
directory
;
private
final
TopologyService
topologyService
;
private
final
DeviceService
deviceService
;
private
final
ObjectMapper
mapper
=
new
ObjectMapper
();
private
Connection
connection
;
private
final
DeviceService
deviceService
;
private
final
LinkService
linkService
;
private
final
HostService
hostService
;
private
final
MastershipService
mastershipService
;
private
final
DeviceListener
deviceListener
=
new
InternalDeviceListener
();
private
final
LinkListener
linkListener
=
new
InternalLinkListener
();
private
final
HostListener
hostListener
=
new
InternalHostListener
();
private
final
MastershipListener
mastershipListener
=
new
InternalMastershipListener
();
// TODO: extract into an external & durable state; good enough for now and demo
private
static
Map
<
String
,
ObjectNode
>
metaUi
=
new
HashMap
<>();
...
...
@@ -74,81 +92,219 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage, TopologyListe
* @param directory service directory
*/
public
TopologyWebSocket
(
ServiceDirectory
directory
)
{
this
.
directory
=
directory
;
topologyService
=
directory
.
get
(
TopologyService
.
class
);
this
.
directory
=
checkNotNull
(
directory
,
"Directory cannot be null"
);
deviceService
=
directory
.
get
(
DeviceService
.
class
);
linkService
=
directory
.
get
(
LinkService
.
class
);
hostService
=
directory
.
get
(
HostService
.
class
);
mastershipService
=
directory
.
get
(
MastershipService
.
class
);
}
@Override
public
void
onOpen
(
Connection
connection
)
{
this
.
connection
=
connection
;
deviceService
.
addListener
(
deviceListener
);
linkService
.
addListener
(
linkListener
);
hostService
.
addListener
(
hostListener
);
mastershipService
.
addListener
(
mastershipListener
);
// Register for topology events...
if
(
topologyService
!=
null
&&
deviceService
!=
null
)
{
topologyService
.
addListener
(
this
);
Topology
topology
=
topologyService
.
currentTopology
();
TopologyGraph
graph
=
topologyService
.
getGraph
(
topology
);
for
(
TopologyVertex
vertex
:
graph
.
getVertexes
())
{
sendMessage
(
message
(
new
DeviceEvent
(
DEVICE_ADDED
,
deviceService
.
getDevice
(
vertex
.
deviceId
()))));
}
sendAllDevices
();
sendAllLinks
();
}
for
(
TopologyEdge
edge
:
graph
.
getEdges
())
{
sendMessage
(
message
(
new
LinkEvent
(
LINK_ADDED
,
edge
.
link
())));
}
private
void
sendAllDevices
()
{
for
(
Device
device
:
deviceService
.
getDevices
())
{
sendMessage
(
deviceMessage
(
new
DeviceEvent
(
DEVICE_ADDED
,
device
)));
}
}
}
else
{
sendMessage
(
message
(
"error"
,
"No topology service!!!"
));
private
void
sendAllLinks
()
{
for
(
Link
link
:
linkService
.
getLinks
())
{
sendMessage
(
linkMessage
(
new
LinkEvent
(
LINK_ADDED
,
link
)));
}
}
@Override
public
void
onClose
(
int
closeCode
,
String
message
)
{
TopologyService
topologyService
=
directory
.
get
(
TopologyService
.
class
);
if
(
topologyService
!=
null
)
{
topologyService
.
removeListener
(
this
);
}
deviceService
.
removeListener
(
deviceListener
);
linkService
.
removeListener
(
linkListener
);
hostService
.
removeListener
(
hostListener
);
mastershipService
.
removeListener
(
mastershipListener
);
}
@Override
public
void
onMessage
(
String
data
)
{
try
{
ObjectNode
event
=
(
ObjectNode
)
mapper
.
reader
().
readTree
(
data
);
String
type
=
event
.
path
(
"event"
).
asText
(
"unknown"
);
ObjectNode
payload
=
(
ObjectNode
)
event
.
path
(
"payload"
);
switch
(
type
)
{
case
"updateMeta"
:
metaUi
.
put
(
payload
.
path
(
"id"
).
asText
(),
payload
);
break
;
case
"requestPath"
:
findPath
(
deviceId
(
payload
.
path
(
"one"
).
asText
()),
deviceId
(
payload
.
path
(
"two"
).
asText
()));
default
:
break
;
String
type
=
string
(
event
,
"event"
,
"unknown"
);
if
(
type
.
equals
(
"showDetails"
))
{
showDetails
(
event
);
}
else
if
(
type
.
equals
(
"updateMeta"
))
{
updateMetaInformation
(
event
);
}
else
if
(
type
.
equals
(
"requestPath"
))
{
sendPath
(
event
);
}
else
if
(
type
.
equals
(
"requestTraffic"
))
{
sendTraffic
(
event
);
}
else
if
(
type
.
equals
(
"cancelTraffic"
))
{
cancelTraffic
(
event
);
}
}
catch
(
IOException
e
)
{
System
.
out
.
println
(
"Received: "
+
data
);
}
}
private
void
findPath
(
DeviceId
one
,
DeviceId
two
)
{
Set
<
Path
>
paths
=
topologyService
.
getPaths
(
topologyService
.
currentTopology
(),
one
,
two
);
if
(!
paths
.
isEmpty
())
{
ObjectNode
payload
=
mapper
.
createObjectNode
();
ArrayNode
links
=
mapper
.
createArrayNode
();
// Sends the specified data to the client.
private
void
sendMessage
(
ObjectNode
data
)
{
try
{
connection
.
sendMessage
(
data
.
toString
());
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
// Retrieves the payload from the specified event.
private
ObjectNode
payload
(
ObjectNode
event
)
{
return
(
ObjectNode
)
event
.
path
(
"payload"
);
}
// Returns the specified node property as a number
private
long
number
(
ObjectNode
node
,
String
name
)
{
return
node
.
path
(
name
).
asLong
();
}
Path
path
=
paths
.
iterator
().
next
();
for
(
Link
link
:
path
.
links
())
{
links
.
add
(
compactLinkString
(
link
));
}
// Returns the specified node property as a string.
private
String
string
(
ObjectNode
node
,
String
name
)
{
return
node
.
path
(
name
).
asText
();
}
// Returns the specified node property as a string.
private
String
string
(
ObjectNode
node
,
String
name
,
String
defaultValue
)
{
return
node
.
path
(
name
).
asText
(
defaultValue
);
}
// Returns the specified set of IP addresses as a string.
private
String
ip
(
Set
<
IpAddress
>
ipAddresses
)
{
Iterator
<
IpAddress
>
it
=
ipAddresses
.
iterator
();
return
it
.
hasNext
()
?
it
.
next
().
toString
()
:
"unknown"
;
}
// Encodes the specified host location into a JSON object.
private
ObjectNode
location
(
ObjectMapper
mapper
,
HostLocation
location
)
{
return
mapper
.
createObjectNode
()
.
put
(
"device"
,
location
.
deviceId
().
toString
())
.
put
(
"port"
,
location
.
port
().
toLong
());
}
// Encodes the specified list of labels a JSON array.
private
ArrayNode
labels
(
ObjectMapper
mapper
,
String
...
labels
)
{
ArrayNode
json
=
mapper
.
createArrayNode
();
for
(
String
label
:
labels
)
{
json
.
add
(
label
);
}
return
json
;
}
// Produces JSON structure from annotations.
private
JsonNode
props
(
Annotations
annotations
)
{
ObjectNode
props
=
mapper
.
createObjectNode
();
for
(
String
key
:
annotations
.
keys
())
{
props
.
put
(
key
,
annotations
.
value
(
key
));
}
return
props
;
}
// Produces a log message event bound to the client.
private
ObjectNode
message
(
String
severity
,
long
id
,
String
message
)
{
return
envelope
(
"message"
,
id
,
mapper
.
createObjectNode
()
.
put
(
"severity"
,
severity
)
.
put
(
"message"
,
message
));
}
payload
.
set
(
"links"
,
links
);
sendMessage
(
envelope
(
"showPath"
,
payload
));
// Puts the payload into an envelope and returns it.
private
ObjectNode
envelope
(
String
type
,
long
sid
,
ObjectNode
payload
)
{
ObjectNode
event
=
mapper
.
createObjectNode
();
event
.
put
(
"event"
,
type
);
if
(
sid
>
0
)
{
event
.
put
(
"sid"
,
sid
);
}
// TODO: when no path, send a message to the client
event
.
set
(
"payload"
,
payload
);
return
event
;
}
// Sends back device or host details.
private
void
showDetails
(
ObjectNode
event
)
{
ObjectNode
payload
=
payload
(
event
);
String
type
=
string
(
payload
,
"type"
,
"unknown"
);
if
(
type
.
equals
(
"device"
))
{
sendMessage
(
deviceDetails
(
deviceId
(
string
(
payload
,
"id"
)),
number
(
event
,
"sid"
)));
}
else
if
(
type
.
equals
(
"host"
))
{
sendMessage
(
hostDetails
(
hostId
(
string
(
payload
,
"id"
)),
number
(
event
,
"sid"
)));
}
}
// Updates device/host meta information.
private
void
updateMetaInformation
(
ObjectNode
event
)
{
ObjectNode
payload
=
payload
(
event
);
metaUi
.
put
(
string
(
payload
,
"id"
),
payload
);
}
// Sends path message.
private
void
sendPath
(
ObjectNode
event
)
{
ObjectNode
payload
=
payload
(
event
);
long
id
=
number
(
event
,
"sid"
);
DeviceId
one
=
deviceId
(
string
(
payload
,
"one"
));
DeviceId
two
=
deviceId
(
string
(
payload
,
"two"
));
ObjectNode
response
=
findPath
(
one
,
two
);
if
(
response
!=
null
)
{
sendMessage
(
envelope
(
"showPath"
,
id
,
response
));
}
else
{
sendMessage
(
message
(
"warn"
,
id
,
"No path found"
));
}
}
// Sends traffic message.
private
void
sendTraffic
(
ObjectNode
event
)
{
ObjectNode
payload
=
payload
(
event
);
long
id
=
number
(
event
,
"sid"
);
IntentId
intentId
=
IntentId
.
valueOf
(
payload
.
path
(
"intentId"
).
asLong
());
if
(
payload
!=
null
)
{
payload
.
put
(
"traffic"
,
true
);
sendMessage
(
envelope
(
"showPath"
,
id
,
payload
));
}
else
{
sendMessage
(
message
(
"warn"
,
id
,
"No path found"
));
}
}
// Cancels sending traffic messages.
private
void
cancelTraffic
(
ObjectNode
event
)
{
// TODO: implement this
}
// Finds the path between the specified devices.
private
ObjectNode
findPath
(
DeviceId
one
,
DeviceId
two
)
{
PathService
pathService
=
directory
.
get
(
PathService
.
class
);
Set
<
Path
>
paths
=
pathService
.
getPaths
(
one
,
two
);
if
(
paths
.
isEmpty
())
{
return
null
;
}
else
{
return
pathMessage
(
paths
.
iterator
().
next
());
}
}
// Produces a path message to the client.
private
ObjectNode
pathMessage
(
Path
path
)
{
ObjectNode
payload
=
mapper
.
createObjectNode
();
ArrayNode
links
=
mapper
.
createArrayNode
();
for
(
Link
link
:
path
.
links
())
{
links
.
add
(
compactLinkString
(
link
));
}
payload
.
set
(
"links"
,
links
);
return
payload
;
}
/**
...
...
@@ -163,16 +319,8 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage, TopologyListe
}
private
void
sendMessage
(
String
data
)
{
try
{
connection
.
sendMessage
(
data
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
// Produces a link event message to the client.
private
String
m
essage
(
DeviceEvent
event
)
{
private
ObjectNode
deviceM
essage
(
DeviceEvent
event
)
{
Device
device
=
event
.
subject
();
ObjectNode
payload
=
mapper
.
createObjectNode
()
.
put
(
"id"
,
device
.
id
().
toString
())
...
...
@@ -183,7 +331,7 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage, TopologyListe
ArrayNode
labels
=
mapper
.
createArrayNode
();
labels
.
add
(
device
.
id
().
toString
());
labels
.
add
(
device
.
chassisId
().
toString
());
labels
.
add
(
"
"
);
// compact no-label view
labels
.
add
(
""
);
// compact no-label view
labels
.
add
(
device
.
annotations
().
value
(
"name"
));
// Add labels, props and stuff the payload into envelope.
...
...
@@ -197,11 +345,11 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage, TopologyListe
String
type
=
(
event
.
type
()
==
DEVICE_ADDED
)
?
"addDevice"
:
((
event
.
type
()
==
DEVICE_REMOVED
)
?
"removeDevice"
:
"updateDevice"
);
return
envelope
(
type
,
payload
);
return
envelope
(
type
,
0
,
payload
);
}
// Produces a link event message to the client.
private
String
m
essage
(
LinkEvent
event
)
{
private
ObjectNode
linkM
essage
(
LinkEvent
event
)
{
Link
link
=
event
.
subject
();
ObjectNode
payload
=
mapper
.
createObjectNode
()
.
put
(
"type"
,
link
.
type
().
toString
().
toLowerCase
())
...
...
@@ -211,43 +359,112 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage, TopologyListe
.
put
(
"dst"
,
link
.
dst
().
deviceId
().
toString
())
.
put
(
"dstPort"
,
link
.
dst
().
port
().
toString
());
String
type
=
(
event
.
type
()
==
LINK_ADDED
)
?
"addLink"
:
((
event
.
type
()
==
LINK_REMOVED
)
?
"removeLink"
:
"
remov
eLink"
);
return
envelope
(
type
,
payload
);
((
event
.
type
()
==
LINK_REMOVED
)
?
"removeLink"
:
"
updat
eLink"
);
return
envelope
(
type
,
0
,
payload
);
}
// Produces JSON structure from annotations.
private
JsonNode
props
(
Annotations
annotations
)
{
ObjectNode
props
=
mapper
.
createObjectNode
();
for
(
String
key
:
annotations
.
keys
())
{
props
.
put
(
key
,
annotations
.
value
(
key
));
// Produces a host event message to the client.
private
ObjectNode
hostMessage
(
HostEvent
event
)
{
Host
host
=
event
.
subject
();
ObjectNode
payload
=
mapper
.
createObjectNode
()
.
put
(
"id"
,
host
.
id
().
toString
());
payload
.
set
(
"cp"
,
location
(
mapper
,
host
.
location
()));
payload
.
set
(
"labels"
,
labels
(
mapper
,
ip
(
host
.
ipAddresses
()),
host
.
mac
().
toString
()));
return
payload
;
}
// Returns device details response.
private
ObjectNode
deviceDetails
(
DeviceId
deviceId
,
long
sid
)
{
Device
device
=
deviceService
.
getDevice
(
deviceId
);
Annotations
annot
=
device
.
annotations
();
int
portCount
=
deviceService
.
getPorts
(
deviceId
).
size
();
return
envelope
(
"showDetails"
,
sid
,
json
(
deviceId
.
toString
(),
device
.
type
().
toString
().
toLowerCase
(),
new
Prop
(
"Name"
,
annot
.
value
(
"name"
)),
new
Prop
(
"Vendor"
,
device
.
manufacturer
()),
new
Prop
(
"H/W Version"
,
device
.
hwVersion
()),
new
Prop
(
"S/W Version"
,
device
.
swVersion
()),
new
Prop
(
"Serial Number"
,
device
.
serialNumber
()),
new
Separator
(),
new
Prop
(
"Latitude"
,
annot
.
value
(
"latitude"
)),
new
Prop
(
"Longitude"
,
annot
.
value
(
"longitude"
)),
new
Prop
(
"Ports"
,
Integer
.
toString
(
portCount
))));
}
// Returns host details response.
private
ObjectNode
hostDetails
(
HostId
hostId
,
long
sid
)
{
Host
host
=
hostService
.
getHost
(
hostId
);
Annotations
annot
=
host
.
annotations
();
return
envelope
(
"showDetails"
,
sid
,
json
(
hostId
.
toString
(),
"host"
,
new
Prop
(
"MAC"
,
host
.
mac
().
toString
()),
new
Prop
(
"IP"
,
host
.
ipAddresses
().
toString
()),
new
Separator
(),
new
Prop
(
"Latitude"
,
annot
.
value
(
"latitude"
)),
new
Prop
(
"Longitude"
,
annot
.
value
(
"longitude"
))));
}
// Produces JSON property details.
private
ObjectNode
json
(
String
id
,
String
type
,
Prop
...
props
)
{
ObjectMapper
mapper
=
new
ObjectMapper
();
ObjectNode
result
=
mapper
.
createObjectNode
()
.
put
(
"id"
,
id
).
put
(
"type"
,
type
);
ObjectNode
pnode
=
mapper
.
createObjectNode
();
ArrayNode
porder
=
mapper
.
createArrayNode
();
for
(
Prop
p
:
props
)
{
porder
.
add
(
p
.
key
);
pnode
.
put
(
p
.
key
,
p
.
value
);
}
return
props
;
result
.
set
(
"propOrder"
,
porder
);
result
.
set
(
"props"
,
pnode
);
return
result
;
}
// Produces a log message event bound to the client.
private
String
message
(
String
severity
,
String
message
)
{
return
envelope
(
"message"
,
mapper
.
createObjectNode
()
.
put
(
"severity"
,
severity
)
.
put
(
"message"
,
message
));
// Auxiliary key/value carrier.
private
class
Prop
{
private
final
String
key
;
private
final
String
value
;
protected
Prop
(
String
key
,
String
value
)
{
this
.
key
=
key
;
this
.
value
=
value
;
}
}
// Puts the payload into an envelope and returns it.
private
String
envelope
(
String
type
,
ObjectNode
payload
)
{
ObjectNode
event
=
mapper
.
createObjectNode
();
event
.
put
(
"event"
,
type
);
event
.
set
(
"payload"
,
payload
);
return
event
.
toString
();
private
class
Separator
extends
Prop
{
protected
Separator
()
{
super
(
"-"
,
""
);
}
}
@Override
public
void
event
(
TopologyEvent
event
)
{
for
(
Event
reason
:
event
.
reasons
())
{
if
(
reason
instanceof
DeviceEvent
)
{
sendMessage
(
message
((
DeviceEvent
)
reason
));
}
else
if
(
reason
instanceof
LinkEvent
)
{
sendMessage
(
message
((
LinkEvent
)
reason
));
}
private
class
InternalDeviceListener
implements
DeviceListener
{
@Override
public
void
event
(
DeviceEvent
event
)
{
sendMessage
(
deviceMessage
(
event
));
}
}
private
class
InternalLinkListener
implements
LinkListener
{
@Override
public
void
event
(
LinkEvent
event
)
{
sendMessage
(
linkMessage
(
event
));
}
}
private
class
InternalHostListener
implements
HostListener
{
@Override
public
void
event
(
HostEvent
event
)
{
sendMessage
(
hostMessage
(
event
));
}
}
private
class
InternalMastershipListener
implements
MastershipListener
{
@Override
public
void
event
(
MastershipEvent
event
)
{
}
}
}
...
...
Please
register
or
login
to post a comment