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