opendaylight architecture ed warnicke – 2015-06-26 note: read with animations
TRANSCRIPT
OpenDaylight ArchitectureEd Warnicke – 2015-06-26
Note: Read with animations
2
Yangtools – What is Yang?• Yang is a modeling language• Models semantics and data
organization• Models can be ‘augmented’• Can model:
• Config/Operational data as a tree• RPCs• Notifications• Text base• Simple Compact
• Standard based (RFC 6020)
3
Yangtools – What does Yangtools do?• Generates Java code from Yang• Provides ‘Codecs’ to convert
• Generated Java classes to DOM• DOM to various formats
• XML• JSON• Etc
• ‘Codecs’ make possible automatic:• RESTCONF• Netconf• Other bindings (AMQP expected this
summer)
Java code
xml
json
exi
Yang to Java Example - typedef
4
Yang Java
public class BridgeName implements Serializable { private final String _value;
@ConstructorProperties("value") public BridgeName(String _value) { … } public BridgeName(BridgeName source) { this._value = source._value; }
public String getValue() { return _value; } …}
typedef bridge-name { type string;}
Yang to Java Example - grouping
5
Yang Java
public interface BridgeAttributes extends DataObject { BridgeName getBridgeName(); …}
grouping bridge-attributes { leaf bridge-name { type bridge-name; } …}
Yang to Java Example - container - interface
6
Yang Java
public interface ConnectionInfo extends Augmentable<ConnectionInfo>, ConnectionInfoAttributes { }
container connection-info { uses connection-info-attributes;}
Yang to Java Example - container - builder
7
Yang Java
public class ConnectionInfoBuilder implements Builder <ConnectionInfo> { /* fields */ public void setRemoteIp(IpAddress value) … public IpAddress getRemoteIp() … public ConnectionInfo build() { return new ConnectionInfoImpl(this); } }
container connection-info { uses connection-info-attributes;}
Yang to Java Example - list - interface
8
Yang Java
public interface ControllerEntry extends Augmentable<ControllerEntry>, Identifiable<ControllerEntryKey> { Uri getTarget();
ControllerEntryKey getKey(); …}
list controller-entry { key “target” leaf target { type inet:uri; }}
Yang to Java Example - list - builder
9
Yang Java
public class ControllerEntryBuilder implements Builder <ControllerEntry> { /* fields */ public ControllerEntryBuilder setTarget(Uri value) { … } … public Uri getTarget(Uri value) {…} ControllerEntryKey getKey() {…} … public ControllerEntry build() { return new ControllerEntryImpl(this); } …}
list controller-entry { key “target” leaf target { type inet:uri; }}
Yang to Java Example - rpc – service interface
10
Yang Java
public interface HelloService extends RpcService { Future<RpcResult<HelloWorldOutput>> helloWorld( HelloWorldInput input);
}
rpc hello-world { input { leaf name { type string; } } output { leaf greating { type string; } }}
Yang to Java Example - rpc – input interface
11
Yang Java
public interface HelloWorldInput extends DataObject, Augmentable<HelloWorldInput> { String getName();
}
rpc hello-world { input { leaf name { type string; } } output { leaf greating { type string; } }}
Yang to Java Example - rpc – input builder
12
Yang Java
public class HelloWorldInputBuilder implements Builder <HelloWorldInput> { /* fields */
public HelloWorldInputBuilder setName(String value) { this._name = value; return this; } public HelloWorldInput build() { return new HelloWorldInputImpl(this); } …}
rpc hello-world { input { leaf name { type string; } } output { leaf greating { type string; } }}
Yang to Java Example - rpc – output interface
13
Yang Java
public interface HelloWorldOutput extends DataObject, Augmentable<HelloWorldOutput> { String getGreating();
}
rpc hello-world { input { leaf name { type string; } } output { leaf greating { type string; } }}
Yang to Java Example - rpc – output builder
14
Yang Java
public class HelloWorldOutputBuilder implements Builder <HelloWorldOutput> { /* fields */
public HelloWorldOutputBuilder setName(String value) { this._name = value; return this; } public HelloWorldOutput build() { return new HelloWorldOutputImpl(this); } …}
rpc hello-world { input { leaf name { type string; } } output { leaf greating { type string; } }}
Yang to Java Example - notification - interface
15
Yang Java
public interface RandomGreetingNotification extends ChildOf<DataObject>, Augmentable<RandomGreetingNotification>, Notification { String getRandomGreeting();}
notification random-greeting-notification { leaf random-greeting { type string; }}
Yang to Java Example - notification - builder
16
Yang Java
public class RandomGreetingNotificationBuilder implements Builder<RandomGreetingNotification> {
public RandomGreetingNotificationBuilder setRandomGreeting(String value) { this._randomGreeting = value; return this; }
public RandomGreetingNotification build() { return new RandomGreetingNotificationImpl(this); } …}
notification random-greeting-notification { leaf random-greeting { type string; }}
17
Yang to Java benefits• Consistent Data Transfer Objects (DTOs) everywhere
• Immutable: to avoid thread contention• Strongly typed: reduce coding errors• Consistent: reduce learning curve• Improvable – generation can be improved and all DTOs get those improvements
immediately system wide• Automated Bindings:
• restconf – xml and json• netconf• amqp and xmpp – on the horizon
• Runtime Generatable
18
MD-SAL – 3 Brokers
Notification Broker
publish
notify
Data Broker
notify
put
store
RPC Broker
call
19
OpenDaylight Platform
NETCONF
MD-SAL
...Flow-Capable Node Inventory Manager
Model
Statistics Manager
Model
OpenFlow Topology Exporter
Model
BGP-LS Topology Exporter
Model
Datastore – key concepts• Yang data is a tree• Two Logical Data Stores
• config• operational
• Unified View• InstanceIdentifier:
• Pointer to a node p1 p2
BGP-LSBGPv4 BGPv6
nodes links prefixes
n1 n2 nx l2l1... ... lx ... px
OpenFlow
Groups
Table/1
nc:1 nc:2
/operational /config
network-topo nodes
Flow/2
of:1of:2
Of:n......
TablesMeters
Table/2 Table/n
Flow/1 Flow/n......
Ports
Table-stats
Flow-statsFlow-stats
20
Datastore – Transactions – Reading and Writing
ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();Optional<Node> nodeOptional;nodeOptional = transaction.read( LogicalDataStore.OPERATIONAL, n1InstanceIdentifier);transaction.put( LogicalDataStore.CONFIG, n2InstanceIdentifier, topologyNodeBuilder.build());transaction.delete( LogicalDataStore.CONFIG, n3InstanceIdentifier);CheckedFuture future;future = transaction.submit();
n1
/operational /config
network-topo
BGPv4overlay1
nodesnodes
Datastore
n3n1
transaction
n2n3
21
Datastore – Transactions – MergingWriteOnlyTransaction transaction = dataBroker.newWriteOnlyTransaction();InstanceIdentifier<Node> path = InstanceIdentifier .create(NetworkTopology.class) .child(Topology.class, new TopologyKey(
“overlay1”));transaction.merge( LogicalDataStore.CONFIG, path, topologyBuilder.build());CheckedFuture future;future = transaction.submit();
n1
/operational /config
network-topo
BGPv4overlay1
nodesnodes
Datastore
n3n1
transaction
nodes
n4
overlay1
n4
22
Datastore – Transactions – Merge vs PutWriteOnlyTransaction transaction = dataBroker.newWriteOnlyTransaction();InstanceIdentifier<Node> path = InstanceIdentifier .create(NetworkTopology.class) .child(Topology.class, new TopologyKey(
“overlay1”));transaction.put( LogicalDataStore.CONFIG, path, topologyBuilder.build());CheckedFuture future;future = transaction.submit();
n1
/operational /config
network-topo
BGPv4overlay1
nodesnodes
Datastore
n3n1
transaction
nodes
n4
overlay1
n4
23
n3
DataChangeListeners – Finding out about change
n1
/operational /config
network-topo
BGPv4overlay1
nodesnodes
Datastore
n3n1
transaction
nodes
n4
overlay1
n4
dataBroker.registerDataChangeListener( LogicalDatastoreType.CONFIGURATION, myInstanceId, myDataChangeListener, DataChangeScope.SUBTREE);
myDataChangeListener
AsyncDataChangeEvent
created deleted updated original
n4
overlay1
n3
nodes
n4n4
overlay1
nodes
24
RPCs – Unicast Messages• RPCs allow you to:
• Send a message• Receive a response• Asynchronously• Without knowledge of provider of
implementation
• RPCs come in two flavors:• Global – One receiver• Routed – One receiver per context
Consumer MD-SAL Provider
25
RPCs – Sending a Message - SynchronousHelloService helloService= session.getRpcService(HelloService.class);
Future<RpcResult<HelloWorldOutput>> future; future= helloService .helloWorld(helloWorldInput);HelloWorldOutput helloWorldOutput = future.get().getResult();
consumer MD-SAL
getRpcService()
return: helloService
helloServicefuture
helloWorld(helloWorldInput)
return: future
get()
return: RpcResult<HelloWorldOutput>
set(helloOutput)
26
RPCs – Sending a Message - AsynchronousHelloService helloService= session.getRpcService(HelloService.class);
Future<RpcResult<HelloWorldOutput>> future; future= helloService .helloWorld(helloWorldInput);
while(! future.isDone()) { /* Do other work */}
HelloWorldOutput helloWorldOutput = future.get().getResult();
consumer MD-SAL
getRpcService()
return: helloService
helloServicefuture
helloWorld(helloWorldInput)
return: future
get()
return: RpcResult<HelloWorldOutput>
set(helloOutput)
isDone()
false
isDone()
true
27
Global RPCs – processing a message - Sync
public class HelloWorldImpl implements HelloService {
public HelloWorldImpl(ProviderContext session){ session.addRpcImplementation(
HelloService.class, this);
} @Override public Future<RpcResult<HelloWorldOutput>> helloWorld(HelloWorldInput input) { /* construct output */ return RpcResultBuilder
.success(helloWorldOutput)
.buildFuture(); }}
MD-SAL
addRpcImplementation(this)
helloWorldImpl
helloWorld(helloWorldInput)
return: future
28
Global RPCs – processing a message - Sync
public class HelloWorldImpl implements HelloService {
public HelloWorldImpl(ProviderContext session){ session.addRpcImplementation(
HelloService.class, this);
} @Override public Future<RpcResult<HelloWorldOutput>> helloWorld(HelloWorldInput input) { /* construct output */ return RpcResultBuilder
.success(helloWorldOutput)
.buildFuture(); }}
MD-SAL
addRpcImplementation(this)
helloWorldImpl
helloWorld(helloWorldInput)
return: future
29
Global RPCs – processing a message - ASync
public class HelloWorldImpl implements HelloService { public HelloWorldImpl(ProviderContext session){ session.addRpcImplementation( HelloService.class, this); } @Override public Future<RpcResult<HelloWorldOutput>> helloWorld(HelloWorldInput input) { SettableFuture future = new SettableFuture(); process (input,future); return future; }}
MD-SAL
addRpcImplementation(this)
helloWorldImpl
helloWorld(helloWorldInput)
return: future
future
process(helloWorldInput,future)
30
Global RPCs – processing a message - ASync
public class HelloWorldImpl implements HelloService { /* * see previous slide for * calls to addRpcImplementation * and the helloWorld method */ private process(HelloWorldInput input, SettableFuture future) { /* process in new thread */ future.set(RpcResultBuilder
.success(helloWorldOutput) .build()); }}
MD-SAL
addRpcImplementation(this)
helloWorldImpl
helloWorld(helloWorldInput)
return: future
future
set(helloOutput)
process(helloWorldInput,future)
31
Routed RPCs – What are they?• A Unicast Message
• Well defined Input/Output• Processor is context dependent
• Input includes ‘Context’• InstanceIdentifier
• Pointer to a place in the tree defining message context
• Consumer is unaware RPC is routed
• Registration includes ‘Context’• MD-SAL ‘routes’ to correct
message processor for ‘Context’
Consumer MD-SAL Provider1 Provider2
32
Routed RPCs – processing a message - Sync
public class HelloWorldImpl1 implements HelloService {
public HelloWorldImpl(ProviderContext session){ RoutedRpcRegistration<HelloService> reg1 = session.addRoutedRpcImplementation( HelloService.class, this); reg1.registerPath(MyContext.class,iid1); } /* helloWorld() implementation works as before */}
MD-SAL
addRoutedRpcImplementation(this)
helloWorldImpl1
helloWorld(helloWorldInput1)
return: future
reg1
return: reg2
registerPath(…)
public class HelloWorldImpl2 implements HelloService {
public HelloWorldImpl(ProviderContext session){ RoutedRpcRegistration<HelloService> reg2 = session.addRoutedRpcImplementation( HelloService.class, this); reg2.registerPath(MyContext.class,iid2); } /* helloWorld() implementation works as before */}
helloWorldImpl2reg2
registerPath(…)
addRoutedRpcImplementation(this)
helloWorld(helloWorldInput2)
return: future
return: reg1
33
Let Make a Deal• If you don’t make me show you Routed RPC working Asynchronously• I won’t make you sit through it • Nobody has to know• Online Session Review: mention how epic the Routed RPC Async slide was
34
Notifications - publishing
notificationPublishService.putNotification(notification);
MD-SALpublisher
putNotification(notification)
35
Notifications - subscribingpublic class MyNotificationListener<MyNotification>
implements NotificationListener {
public MyNotificationListener( NotificationService ns) { ns.registerNotificationListener(this); }
onNotification(MyNotification notification){ /* process notification */ }}
MD-SALMyNotificationListener
registerNotificationListener(this)
onNotification(notification)
36
Clustering - Datastore• Datastore
• Sharded• Replicated
• But not everywhere• RAFT algorithm for consistency
n1
/operational /config
network-topo
BGPv4overlay1
nodesnodes
Node -3
n3n1 n4n1
/operational /config
network-topo
BGPv4overlay1
nodesnodes
Node -2
n3n1 n4n1
/operational /config
network-topo
BGPv4overlay1
nodesnodes
Node -1
n3n1 n4
37
Clustering - RPCs• RPCs
• Routed across the cluster Consumer MD-SAL Provider
Node -1
MD-SAL
Node -2