Ovsdb plugin compatibility layer
[ovsdb.git] / openstack / net-virt / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / PortHandler.java
1 /*
2  * Copyright (C) 2013 Red Hat, Inc.
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  * Authors : Madhu Venugopal, Brent Salisbury
9  */
10 package org.opendaylight.ovsdb.openstack.netvirt;
11
12 import org.opendaylight.neutron.spi.INeutronPortAware;
13 import org.opendaylight.neutron.spi.NeutronPort;
14 import org.opendaylight.controller.sal.core.Node;
15 import org.opendaylight.ovsdb.lib.notation.Row;
16 import org.opendaylight.ovsdb.lib.notation.UUID;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
18 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
19 import org.opendaylight.ovsdb.openstack.netvirt.impl.NeutronL3Adapter;
20 import org.opendaylight.ovsdb.compatibility.plugin.api.OvsdbConfigurationService;
21 import org.opendaylight.ovsdb.compatibility.plugin.api.OvsdbConnectionService;
22 import org.opendaylight.ovsdb.compatibility.plugin.api.OvsdbInventoryListener;
23 import org.opendaylight.ovsdb.schema.openvswitch.Interface;
24 import org.opendaylight.ovsdb.schema.openvswitch.Port;
25
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 import java.net.HttpURLConnection;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.concurrent.ConcurrentMap;
33
34 /**
35  * Handle requests for Neutron Port.
36  */
37 public class PortHandler extends AbstractHandler
38                          implements INeutronPortAware {
39
40     /**
41      * Logger instance.
42      */
43     static final Logger logger = LoggerFactory.getLogger(PortHandler.class);
44
45     // The implementation for each of these services is resolved by the OSGi Service Manager
46     private volatile OvsdbConfigurationService ovsdbConfigurationService;
47     private volatile OvsdbConnectionService connectionService;
48     private volatile OvsdbInventoryListener ovsdbInventoryListener;
49     private volatile NeutronL3Adapter neutronL3Adapter;
50
51     /**
52      * Invoked when a port creation is requested
53      * to indicate if the specified port can be created.
54      *
55      * @param port     An instance of proposed new Port object.
56      * @return A HTTP status code to the creation request.
57      */
58     @Override
59     public int canCreatePort(NeutronPort port) {
60         return HttpURLConnection.HTTP_CREATED;
61     }
62
63     /**
64      * Invoked to take action after a port has been created.
65      *
66      * @param port An instance of new Neutron Port object.
67      */
68     @Override
69     public void neutronPortCreated(NeutronPort neutronPort) {
70         int result = canCreatePort(neutronPort);
71         if (result != HttpURLConnection.HTTP_CREATED) {
72             logger.error(" Port create validation failed result - {} ", result);
73             return;
74         }
75
76         enqueueEvent(new NorthboundEvent(neutronPort, Action.ADD));
77     }
78     private void doNeutronPortCreated(NeutronPort neutronPort) {
79         logger.debug(" Port-ADD successful for tenant-id - {}," +
80                      " network-id - {}, port-id - {}",
81                      neutronPort.getTenantID(), neutronPort.getNetworkUUID(),
82                      neutronPort.getID());
83         neutronL3Adapter.handleNeutronPortEvent(neutronPort, Action.ADD);
84     }
85
86     /**
87      * Invoked when a port update is requested
88      * to indicate if the specified port can be changed
89      * using the specified delta.
90      *
91      * @param delta    Updates to the port object using patch semantics.
92      * @param original An instance of the Neutron Port object
93      *                  to be updated.
94      * @return A HTTP status code to the update request.
95      */
96     @Override
97     public int canUpdatePort(NeutronPort delta,
98                              NeutronPort original) {
99         int result = HttpURLConnection.HTTP_OK;
100         /**
101          * To basic validation of the request
102          */
103
104         if ((original == null) || (delta == null)) {
105             logger.error("port object not specified");
106             return HttpURLConnection.HTTP_BAD_REQUEST;
107         }
108         return result;
109     }
110
111     /**
112      * Invoked to take action after a port has been updated.
113      *
114      * @param port An instance of modified Neutron Port object.
115      */
116     @Override
117     public void neutronPortUpdated(NeutronPort neutronPort) {
118         enqueueEvent(new NorthboundEvent(neutronPort, Action.UPDATE));
119     }
120     private void doNeutronPortUpdated(NeutronPort neutronPort) {
121         logger.debug("Handling neutron update port " + neutronPort);
122         neutronL3Adapter.handleNeutronPortEvent(neutronPort, Action.UPDATE);
123     }
124
125     /**
126      * Invoked when a port deletion is requested
127      * to indicate if the specified port can be deleted.
128      *
129      * @param port     An instance of the Neutron Port object to be deleted.
130      * @return A HTTP status code to the deletion request.
131      */
132     @Override
133     public int canDeletePort(NeutronPort port) {
134         return HttpURLConnection.HTTP_OK;
135     }
136
137     /**
138      * Invoked to take action after a port has been deleted.
139      *
140      * @param neutronPort  An instance of deleted Neutron Port object.
141      */
142     @Override
143     public void neutronPortDeleted(NeutronPort neutronPort) {
144
145         int result = canDeletePort(neutronPort);
146         if  (result != HttpURLConnection.HTTP_OK) {
147             logger.error(" deletePort validation failed - result {} ", result);
148             return;
149         }
150
151         enqueueEvent(new NorthboundEvent(neutronPort, Action.DELETE));
152     }
153     private void doNeutronPortDeleted(NeutronPort neutronPort) {
154         logger.debug("Handling neutron delete port " + neutronPort);
155         neutronL3Adapter.handleNeutronPortEvent(neutronPort, Action.DELETE);
156
157         List<Node> nodes = connectionService.getNodes();
158         for (Node node : nodes) {
159             try {
160                 ConcurrentMap<String, Row> portRows =
161                         this.ovsdbConfigurationService.getRows(node,
162                                                         ovsdbConfigurationService.getTableName(node, Port.class));
163                 if (portRows != null) {
164                     for (Row portRow : portRows.values()) {
165                         Port port = ovsdbConfigurationService.getTypedRow(node, Port.class, portRow);
166                         for (UUID interfaceUuid : port.getInterfacesColumn().getData()) {
167                             Row ifaceRow = ovsdbConfigurationService
168                                     .getRow(node,
169                                             ovsdbConfigurationService.getTableName(node, Interface.class),
170                                             interfaceUuid.toString());
171                             Interface iface = ovsdbConfigurationService.getTypedRow(node, Interface.class, ifaceRow);
172                             Map<String, String> externalIds = iface.getExternalIdsColumn().getData();
173
174                             if (externalIds == null) {
175                                 logger.trace("No external_ids seen in {}", iface.getName());
176                                 continue;
177                             }
178
179                             /* Compare Neutron port uuid */
180                             String neutronPortId = externalIds.get(Constants.EXTERNAL_ID_INTERFACE_ID);
181                             if (neutronPortId == null) {
182                                 continue;
183                             }
184
185                             if (neutronPortId.equalsIgnoreCase(neutronPort.getPortUUID())) {
186                                 logger.trace("neutronPortDeleted: Delete interface {}", iface.getName());
187                                 ovsdbConfigurationService.deleteRow(node,
188                                                              ovsdbConfigurationService.getTableName(node, Port.class),
189                                                              port.getUuid().toString());
190                                 break;
191                             }
192                         }
193                     }
194                 }
195             } catch (Exception e) {
196                 logger.error("Exception during handlingNeutron port delete", e);
197             }
198         }
199         logger.debug(" PORT delete successful for tenant-id - {}, " +
200                      " network-id - {}, port-id - {}",
201                      neutronPort.getTenantID(), neutronPort.getNetworkUUID(),
202                      neutronPort.getID());
203
204     }
205
206     /**
207      * Process the event.
208      *
209      * @param abstractEvent the {@link org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent} event to be handled.
210      * @see EventDispatcher
211      */
212     @Override
213     public void processEvent(AbstractEvent abstractEvent) {
214         if (!(abstractEvent instanceof NorthboundEvent)) {
215             logger.error("Unable to process abstract event " + abstractEvent);
216             return;
217         }
218         NorthboundEvent ev = (NorthboundEvent) abstractEvent;
219         switch (ev.getAction()) {
220             case ADD:
221                 doNeutronPortCreated(ev.getPort());
222                 break;
223             case DELETE:
224                 doNeutronPortDeleted(ev.getPort());
225                 break;
226             case UPDATE:
227                 doNeutronPortUpdated(ev.getPort());
228                 break;
229             default:
230                 logger.warn("Unable to process event action " + ev.getAction());
231                 break;
232         }
233     }
234 }