2 * Copyright (C) 2014 SDN Hub, LLC.
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
8 * Authors : Srini Seetharaman
11 package org.opendaylight.ovsdb.openstack.netvirt;
13 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerAware;
14 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolCRUD;
15 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolMemberCRUD;
16 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
17 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancer;
18 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPool;
19 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPoolMember;
20 import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
21 import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;
22 import org.opendaylight.controller.sal.core.Node;
23 import org.opendaylight.controller.switchmanager.ISwitchManager;
24 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
25 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerConfiguration;
26 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerProvider;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
30 import com.google.common.base.Preconditions;
32 import java.net.HttpURLConnection;
33 import java.util.Iterator;
34 import java.util.List;
37 * Handle requests for OpenStack Neutron v2.0 LBaaS API calls for /v2.0/loadbalancers.
40 //TODO: Implement INeutronLoadBalancerHealthMonitorAware, INeutronLoadBalancerListenerAware, INeutronLoadBalancerPoolMemberAware,
42 public class LBaaSHandler extends AbstractHandler
43 implements INeutronLoadBalancerAware {
45 private static final Logger logger = LoggerFactory.getLogger(LBaaSHandler.class);
47 // The implementation for each of these services is resolved by the OSGi Service Manager
48 private volatile INeutronLoadBalancerPoolCRUD neutronLBPoolCache;
49 private volatile INeutronLoadBalancerPoolMemberCRUD neutronLBPoolMemberCache;
50 private volatile INeutronPortCRUD neutronPortsCache;
51 private volatile LoadBalancerProvider loadBalancerProvider;
52 private volatile ISwitchManager switchManager;
55 public int canCreateNeutronLoadBalancer(NeutronLoadBalancer neutronLoadBalancer) {
56 LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLoadBalancer);
57 if (!lbConfig.isValid())
58 return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
60 return HttpURLConnection.HTTP_OK;
64 * Assuming that the pool information is fully populated before this call is made,
65 * we go with creating the LoadBalancerConfiguration object for this call with
66 * all information that is necessary to insert flow_mods
69 public void neutronLoadBalancerCreated(NeutronLoadBalancer neutronLoadBalancer) {
70 logger.debug("Neutron LB Creation : {}", neutronLoadBalancer.toString());
71 enqueueEvent(new NorthboundEvent(neutronLoadBalancer, Action.ADD));
74 private void doNeutronLoadBalancerCreate(NeutronLoadBalancer neutronLoadBalancer) {
75 int result = canCreateNeutronLoadBalancer(neutronLoadBalancer);
76 if (result != HttpURLConnection.HTTP_OK) {
77 logger.debug("Neutron Load Balancer creation failed {} ", result);
80 Preconditions.checkNotNull(loadBalancerProvider);
81 LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLoadBalancer);
83 if (!lbConfig.isValid()) {
84 logger.trace("Neutron LB pool configuration invalid for {} ", lbConfig.getName());
87 for (Node node: this.switchManager.getNodes())
88 loadBalancerProvider.programLoadBalancerRules(node, lbConfig, Action.ADD);
93 public int canUpdateNeutronLoadBalancer(NeutronLoadBalancer delta, NeutronLoadBalancer original) {
94 return HttpURLConnection.HTTP_OK;
98 public void neutronLoadBalancerUpdated(NeutronLoadBalancer neutronLoadBalancer) {
99 enqueueEvent(new NorthboundEvent(neutronLoadBalancer, Action.UPDATE));
104 public int canDeleteNeutronLoadBalancer(NeutronLoadBalancer neutronLoadBalancer) {
105 LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLoadBalancer);
106 if (!lbConfig.isValid())
107 return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
109 return HttpURLConnection.HTTP_OK;
113 public void neutronLoadBalancerDeleted(NeutronLoadBalancer neutronLoadBalancer) {
114 logger.debug("Neutron LB Deletion : {}", neutronLoadBalancer.toString());
115 enqueueEvent(new NorthboundEvent(neutronLoadBalancer, Action.DELETE));
118 private void doNeutronLoadBalancerDelete(NeutronLoadBalancer neutronLoadBalancer) {
119 int result = canDeleteNeutronLoadBalancer(neutronLoadBalancer);
120 if (result != HttpURLConnection.HTTP_OK) {
121 logger.error(" delete Neutron NeutronLoadBalancer Pool validation failed for result - {} ", result);
124 Preconditions.checkNotNull(loadBalancerProvider);
125 LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLoadBalancer);
127 if (!lbConfig.isValid()) {
128 logger.trace("Neutron LB pool configuration invalid for {} ", lbConfig.getName());
131 for (Node node: this.switchManager.getNodes())
132 loadBalancerProvider.programLoadBalancerRules(node, lbConfig, Action.DELETE);
139 * @param abstractEvent the {@link org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent} event to be handled.
140 * @see org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher
143 public void processEvent(AbstractEvent abstractEvent) {
144 if (!(abstractEvent instanceof NorthboundEvent)) {
145 logger.error("Unable to process abstract event " + abstractEvent);
148 NorthboundEvent ev = (NorthboundEvent) abstractEvent;
149 switch (ev.getAction()) {
151 doNeutronLoadBalancerCreate(ev.getLoadBalancer());
153 doNeutronLoadBalancerDelete(ev.getLoadBalancer());
156 * Currently member update requires delete and re-adding
157 * Also, weights and weight updates are not supported
159 doNeutronLoadBalancerDelete(ev.getLoadBalancer());
160 doNeutronLoadBalancerCreate(ev.getLoadBalancer());
163 logger.warn("Unable to process event action " + ev.getAction());
169 * Useful utility for extracting the loadbalancer instance
170 * configuration from the neutron LB cache
172 public LoadBalancerConfiguration extractLBConfiguration(NeutronLoadBalancer neutronLoadBalancer) {
173 String loadBalancerName = neutronLoadBalancer.getLoadBalancerName();
174 String loadBalancerVip = neutronLoadBalancer.getLoadBalancerVipAddress();
175 String loadBalancerSubnetID = neutronLoadBalancer.getLoadBalancerVipSubnetID();
176 LoadBalancerConfiguration lbConfig = new LoadBalancerConfiguration(loadBalancerName, loadBalancerVip);
178 String memberID, memberIP, memberMAC, memberProtocol;
181 for (NeutronLoadBalancerPool neutronLBPool: neutronLBPoolCache.getAllNeutronLoadBalancerPools()) {
182 List<? extends NeutronLoadBalancerPoolMember> members =
183 (List<? extends NeutronLoadBalancerPoolMember>)neutronLBPool.getLoadBalancerPoolMembers();
184 memberProtocol = neutronLBPool.getLoadBalancerPoolProtocol();
186 * Only HTTP and HTTPS are supported as of this version
187 * TODO: Support all TCP load-balancers
189 if (!(memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
190 memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTPS)))
192 for (NeutronLoadBalancerPoolMember neutronLBPoolMember: members) {
193 if (neutronLBPoolMember.getPoolMemberSubnetID().equals(loadBalancerSubnetID)) {
194 memberID = neutronLBPoolMember.getPoolMemberID();
195 memberIP = neutronLBPoolMember.getPoolMemberAddress();
196 memberPort = neutronLBPoolMember.getPoolMemberProtoPort();
197 memberMAC = this.getMacAddress(memberIP);
198 if (memberMAC == null)
200 lbConfig.addMember(memberID, memberIP, memberMAC, memberProtocol, memberPort);
208 * Look up in the NeutronPortsCRUD cache and return the MAC address for a corresponding IP address
209 * @param ipAddr IP address of a member or VM
210 * @return MAC address registered with that IP address
212 public String getMacAddress(String ipAddr) {
213 List<Neutron_IPs> fixedIPs;
214 Iterator<Neutron_IPs> fixedIPIterator;
217 List<NeutronPort> allPorts = neutronPortsCache.getAllPorts();
218 Iterator<NeutronPort> i = allPorts.iterator();
219 while (i.hasNext()) {
220 NeutronPort port = i.next();
221 fixedIPs = port.getFixedIPs();
222 if (fixedIPs != null && fixedIPs.size() > 0) {
223 fixedIPIterator = fixedIPs.iterator();
224 while (fixedIPIterator.hasNext()) {
225 ip = fixedIPIterator.next();
226 if (ip.getIpAddress().equals(ipAddr))
227 return port.getMacAddress();