[CONTROLLER-1587] Fix blueprint assumptions around odl:rpc-service Created: 20/Jan/17 Updated: 25/Jul/23 Resolved: 09/Feb/17 |
|
| Status: | Resolved |
| Project: | controller |
| Component/s: | blueprint |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Bug | ||
| Reporter: | Robert Varga | Assignee: | Robert Varga |
| Resolution: | Done | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
Operating System: All |
||
| Attachments: |
|
||||||||
| Issue Links: |
|
||||||||
| External issue ID: | 7608 | ||||||||
| Description |
|
The odl:rpc-service extension makes assumptions about RPC lifecycle which are not strictly true when the definition is translated to DOMRpcIdentifier, most notably about when an RPC implementation is registered. Current codebase happens to work due to how sal-remoterpc-connector integrates with DOMRpcRouter, but that integration needs to be redone to fix BUG-3128. That in turn breaks assumptions in blueprint. Refine the odl:rpc-service contract to cover registration semantics with respect to routed RPCs and implement it in a way, which will not break in absence of sal-remoterpc-connector. |
| Comments |
| Comment by Robert Varga [ 20/Jan/17 ] |
|
Additional analysis shows that the problem is interaction between blueprint's (and by extension end-user's) expectation versus how RPC routing works. Current BP odl:rpc-service and odl:rpc-implementation can only work as envisioned for binding FooService completely composed of global RPCs. It acts as a dependency activation gate before the component activates. Routed RPCs ('actions' to use RFC7950 term) work in a rather different way, as they come and go as their contexts change. In this case BP wiring really wants to express a dependency on 'someone has promised to instantiate actions'. That contract is currently 'provided' by sal-remoterpc-connector by blanked-subscribing as an implementation for all actions. This has the side-effect of rendering BP dependency wiring in this case not working, for example for OFP's lldp-speaker.xml – it depends on PacketProcessingService, which is supposed to be exported from openflowplugin's blueprint (i.e. OFP instance registers actions for each connect OF switch). But lldp-speaker activation will not be blocked waiting for openflowplugin, but rather it will activate immediately due to sal-remoterpc-connector pretending to provide that promise. Another layer of features is to have beans dynamically start when a specific action (on a context) is registered, but making that work means we have to actually react to actions and RPCs disappearing – this is out of scope of this issue, but needs to be considered in the solution domain here. To solve this issue and BUG-3128 without breaking the world, we will need to provide a partial fix for this issue, then fix sal-remoterpc-connector (and DOMRpcBroker) and then finalize the fix for this issue. |
| Comment by Robert Varga [ 20/Jan/17 ] |
|
The fix is to provide a clear split between actions and rpcs, in a way which is forward-compatible with YANG 1.1 and Java Binding V2 (where each action is its own entity). This will be done by defining a odl:action-service and odl:action-provider, which mirror the semantics of odl:rpc- {service,implementation}. An odl:action-provider designates a bean, which holds the promise to instantiate action instances. As soon as that bean is instantiated, the promise is fulfilled and the promise is populated into DOMRpcRegistry. An odl:action-service declares a dependency to have at least one odl:action-provider active. The terms odl:action-instance and odl:action-implementation are reserved for future use. odl:action-implementation will provide an implementation of an action on a particular context (much like odl:routed-rpc-implementation). odl:action-instance will be used to reference to action-implementation. This will be added to XSD, but will be left unimplemented until such time as true dynamic services are needed. The first part of the fix is to provide these concepts and add a basic compatible implementation, i.e. odl:action-service will be always considered to be fulfilled if a model for it exists. The code will also detect and warn about ambiguous use of odl:rpc-service when the specified interface also contains an action (routed RPC). |
| Comment by Robert Varga [ 26/Jan/17 ] |
|
DOMRpcService contract clarification: https://git.opendaylight.org/gerrit/51034 |
| Comment by Robert Varga [ 27/Jan/17 ] |
|
New action-provider/action-service contracts: https://git.opendaylight.org/gerrit/50784 |
| Comment by Robert Varga [ 02/Feb/17 ] |
| Comment by Tomas Cechvala [ 09/Feb/17 ] |
|
rpc error |
| Comment by Tomas Cechvala [ 09/Feb/17 ] |
|
Attachment rpcerror.txt has been added with description: rpc error |
| Comment by Tomas Cechvala [ 09/Feb/17 ] |
|
log |
| Comment by Tomas Cechvala [ 09/Feb/17 ] |
|
Attachment karaf_log_error.txt has been added with description: log |
| Comment by Tomas Cechvala [ 09/Feb/17 ] |
|
This does not quite work in cluster singleton service our blueprint configuration <bean id="vppRenderer" class="org.opendaylight.controller.config.yang.config.vpp_provider.impl.GbpVppProviderInstance" <odl:rpc-implementation ref="vppRenderer"/> Errors are returned, when sending RPCs to follower node (not leader). NPE is caught here on line 104 @Override However, RPCs are processed correctly when sent to the leader node. |
| Comment by Robert Varga [ 09/Feb/17 ] |
|
Of course it does not. The reason for that is that the GbpVppProviderInstance is not fully initialized by the time it gets registered as a provider – i.e. instantiateServiceInstance() has not been called. This effectively means you cannot use odl:rpc-implementation to inject the bean as an implementation – you have to do it yourself from instantiateServiceInstance()... unless there is a blueprint way to have GbpVppProviderInstance bean created based on singleton service. |
| Comment by Robert Varga [ 09/Feb/17 ] |
|
So with the current setup you are registering an implementation on each node, even before it is fully initialized. Once singleton does its thing, one of the implementations will become operational – but there is a time window when you already have registered it, but it is not initialized. RPCs are always routed to the closest registered instance, in this case it will end up always being the local one – whether it is operational or not. |