Add the openflowplugin-blueprint-config bundles to the features xml
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / SalRegistrationManager.java
1 /**
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.openflowplugin.openflow.md.core.sal;
9
10 import com.google.common.base.Preconditions;
11 import java.math.BigInteger;
12 import java.net.Inet4Address;
13 import java.net.Inet6Address;
14 import java.net.InetAddress;
15 import java.net.InetSocketAddress;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
18 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
19 import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitch;
20 import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationQueueWrapper;
21 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
22 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionListener;
23 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionManager;
24 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SwitchSessionKeyOF;
25 import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdatedBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemovedBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
42 import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
43 import org.opendaylight.yangtools.concepts.ListenerRegistration;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
46 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
47 import org.opendaylight.openflowplugin.openflow.md.core.role.OfEntityManager;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 /**
52  * session and inventory listener implementation
53  */
54 public class SalRegistrationManager implements SessionListener, AutoCloseable {
55
56     private static final Logger LOG = LoggerFactory.getLogger(SalRegistrationManager.class);
57
58     private NotificationProviderService publishService;
59
60     private DataBroker dataService;
61
62     private RpcProviderRegistry rpcProviderRegistry;
63
64     private final SwitchFeaturesUtil swFeaturesUtil;
65
66     private ListenerRegistration<SessionListener> sessionListenerRegistration;
67
68     private OfEntityManager entManager;
69
70     public SalRegistrationManager() {
71         swFeaturesUtil = SwitchFeaturesUtil.getInstance();
72     }
73
74     public NotificationProviderService getPublishService() {
75         return publishService;
76     }
77
78     public void setPublishService(final NotificationProviderService publishService) {
79         this.publishService = publishService;
80     }
81
82     public void setDataService(final DataBroker dataService) {
83         this.dataService = dataService;
84     }
85
86     public void setRpcProviderRegistry(final RpcProviderRegistry rpcProviderRegistry) {
87         this.rpcProviderRegistry = rpcProviderRegistry;
88     }
89
90     public void setOfEntityManager(OfEntityManager entManager) {
91         this.entManager = entManager;
92     }
93
94     public void init() {
95         LOG.debug("init..");
96         sessionListenerRegistration = getSessionManager().registerSessionListener(this);
97         getSessionManager().setNotificationProviderService(publishService);
98         getSessionManager().setDataBroker(dataService);
99         LOG.debug("SalRegistrationManager initialized");
100     }
101
102     @Override
103     public void onSessionAdded(final SwitchSessionKeyOF sessionKey, final SessionContext context) {
104         GetFeaturesOutput features = context.getFeatures();
105         BigInteger datapathId = features.getDatapathId();
106         InstanceIdentifier<Node> identifier = identifierFromDatapathId(datapathId);
107         NodeRef nodeRef = new NodeRef(identifier);
108         NodeId nodeId = nodeIdFromDatapathId(datapathId);
109         ModelDrivenSwitch ofSwitch = new ModelDrivenSwitchImpl(nodeId, identifier,context);
110
111         NotificationQueueWrapper wrappedNotification = new NotificationQueueWrapper(
112                 nodeAdded(ofSwitch, features, nodeRef),
113                 context.getFeatures().getVersion());
114
115         reqOpenflowEntityOwnership(ofSwitch, context, wrappedNotification, rpcProviderRegistry);
116     }
117
118     @Override
119     public void setRole (SessionContext context) {
120         entManager.setSlaveRole(context);
121     }
122
123     @Override
124     public void onSessionRemoved(final SessionContext context) {
125         GetFeaturesOutput features = context.getFeatures();
126         BigInteger datapathId = features.getDatapathId();
127         InstanceIdentifier<Node> identifier = identifierFromDatapathId(datapathId);
128         NodeRef nodeRef = new NodeRef(identifier);
129         NodeId nodeId = nodeIdFromDatapathId(datapathId);
130         unregOpenflowEntityOwnership(nodeId);
131         NodeRemoved nodeRemoved = nodeRemoved(nodeRef);
132
133         CompositeObjectRegistration<ModelDrivenSwitch> registration = context.getProviderRegistration();
134         if (null != registration) {
135             registration.close();
136             context.setProviderRegistration(null);
137         }
138         LOG.debug("ModelDrivenSwitch for {} unregistered from MD-SAL.", datapathId);
139
140         NotificationQueueWrapper wrappedNotification = new NotificationQueueWrapper(
141                 nodeRemoved, context.getFeatures().getVersion());
142         context.getNotificationEnqueuer().enqueueNotification(wrappedNotification);
143     }
144
145     private NodeUpdated nodeAdded(final ModelDrivenSwitch sw, final GetFeaturesOutput features, final NodeRef nodeRef) {
146         NodeUpdatedBuilder builder = new NodeUpdatedBuilder();
147         builder.setId(sw.getNodeId());
148         builder.setNodeRef(nodeRef);
149
150         FlowCapableNodeUpdatedBuilder builder2 = new FlowCapableNodeUpdatedBuilder();
151         try {
152             builder2.setIpAddress(getIpAddressOf(sw));
153             builder2.setPortNumber(getPortNumberOf(sw));
154         } catch (Exception e) {
155             LOG.warn("IP address/Port Number of the node {} cannot be obtained.", sw.getNodeId(), e);
156         }
157         builder2.setSwitchFeatures(swFeaturesUtil.buildSwitchFeatures(features));
158         builder.addAugmentation(FlowCapableNodeUpdated.class, builder2.build());
159
160         return builder.build();
161     }
162
163     private static IpAddress getIpAddressOf(final ModelDrivenSwitch sw) {
164         SessionContext sessionContext = sw.getSessionContext();
165         Preconditions.checkNotNull(sessionContext.getPrimaryConductor(),
166                 "primary conductor must not be NULL -> " + sw.getNodeId());
167         Preconditions.checkNotNull(sessionContext.getPrimaryConductor().getConnectionAdapter(),
168                 "connection adapter of primary conductor must not be NULL -> " + sw.getNodeId());
169         InetSocketAddress remoteAddress = sessionContext.getPrimaryConductor().getConnectionAdapter()
170                 .getRemoteAddress();
171         if (remoteAddress == null) {
172             LOG.warn("IP address of the node {} cannot be obtained. No connection with switch.", sw.getNodeId());
173             return null;
174         }
175         return resolveIpAddress(remoteAddress.getAddress());
176     }
177
178     private static IpAddress resolveIpAddress(final InetAddress address) {
179         String hostAddress = address.getHostAddress();
180         if (address instanceof Inet4Address) {
181             return new IpAddress(new Ipv4Address(hostAddress));
182         }
183         if (address instanceof Inet6Address) {
184             return new IpAddress(new Ipv6Address(hostAddress));
185         }
186         throw new IllegalArgumentException("Unsupported IP address type!");
187     }
188
189     private static PortNumber getPortNumberOf(ModelDrivenSwitch sw) {
190         SessionContext sessionContext = sw.getSessionContext();
191
192         Preconditions.checkNotNull(sessionContext.getPrimaryConductor(),
193                 "primary conductor must not be NULL -> " + sw.getNodeId());
194         Preconditions.checkNotNull(sessionContext.getPrimaryConductor().getConnectionAdapter(),
195                 "connection adapter of primary conductor must not be NULL -> " + sw.getNodeId());
196         InetSocketAddress remoteAddress = sessionContext.getPrimaryConductor().getConnectionAdapter()
197                 .getRemoteAddress();
198         if (remoteAddress == null) {
199             LOG.warn("Port Number of the node {} cannot be obtained. No connection with switch.", sw.getNodeId());
200             return null;
201         }
202         return resolvePortNumber(remoteAddress.getPort());
203     }
204
205     private static PortNumber resolvePortNumber(int port) {
206         PortNumber portNo = new PortNumber(port);
207         return portNo;
208     }
209
210     private static NodeRemoved nodeRemoved(final NodeRef nodeRef) {
211         NodeRemovedBuilder builder = new NodeRemovedBuilder();
212         builder.setNodeRef(nodeRef);
213         return builder.build();
214     }
215
216     public static InstanceIdentifier<Node> identifierFromDatapathId(final BigInteger datapathId) {
217         NodeKey nodeKey = nodeKeyFromDatapathId(datapathId);
218         InstanceIdentifierBuilder<Node> builder = InstanceIdentifier.builder(Nodes.class).child(Node.class, nodeKey);
219         return builder.build();
220     }
221
222     public static NodeKey nodeKeyFromDatapathId(final BigInteger datapathId) {
223         return new NodeKey(nodeIdFromDatapathId(datapathId));
224     }
225
226     public static NodeId nodeIdFromDatapathId(final BigInteger datapathId) {
227         // FIXME: Convert to textual representation of datapathID
228         String current = String.valueOf(datapathId);
229         return new NodeId("openflow:" + current);
230     }
231
232     public SessionManager getSessionManager() {
233         return OFSessionUtil.getSessionManager();
234     }
235
236     @Override
237     public void close() {
238         dataService = null;
239         rpcProviderRegistry = null;
240         publishService = null;
241         if (sessionListenerRegistration != null) {
242             sessionListenerRegistration.close();
243         }
244     }
245
246     private void reqOpenflowEntityOwnership(ModelDrivenSwitch ofSwitch,
247                                             SessionContext context,
248                                             NotificationQueueWrapper wrappedNotification,
249                                             RpcProviderRegistry rpcProviderRegistry) {
250         context.setValid(true);
251         entManager.requestOpenflowEntityOwnership(ofSwitch, context, wrappedNotification, rpcProviderRegistry);
252     }
253
254     private void unregOpenflowEntityOwnership(NodeId nodeId) {
255         entManager.unregisterEntityOwnershipRequest(nodeId);
256     }
257
258 }