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.sal.core.Node;
21 import org.opendaylight.controller.switchmanager.ISwitchManager;
22 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
23 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerConfiguration;
24 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerProvider;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
28 import com.google.common.base.Preconditions;
30 import java.net.HttpURLConnection;
31 import java.util.List;
34 * Handle requests for OpenStack Neutron v2.0 LBaaS API calls for /v2.0/loadbalancers.
37 //TODO: Implement INeutronLoadBalancerHealthMonitorAware, INeutronLoadBalancerListenerAware, INeutronLoadBalancerPoolMemberAware,
39 public class LBaaSHandler extends AbstractHandler
40 implements INeutronLoadBalancerAware {
42 private static final Logger logger = LoggerFactory.getLogger(LBaaSHandler.class);
44 // The implementation for each of these services is resolved by the OSGi Service Manager
45 private volatile INeutronLoadBalancerPoolCRUD neutronLBPoolCache;
46 private volatile INeutronLoadBalancerPoolMemberCRUD neutronLBPoolMemberCache;
47 private volatile INeutronPortCRUD neutronPortsCache;
48 private volatile LoadBalancerProvider loadBalancerProvider;
49 private volatile ISwitchManager switchManager;
52 public int canCreateNeutronLoadBalancer(NeutronLoadBalancer neutronLB) {
53 LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLB);
54 if (!lbConfig.isValid())
55 return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
57 return HttpURLConnection.HTTP_OK;
61 * Assuming that the pool information is fully populated before this call is made,
62 * we go with creating the LoadBalancerConfiguration object for this call with
63 * all information that is necessary to insert flow_mods
66 public void neutronLoadBalancerCreated(NeutronLoadBalancer neutronLB) {
67 logger.debug("Neutron LB Creation : {}", neutronLB.toString());
68 enqueueEvent(new NorthboundEvent(neutronLB, Action.ADD));
71 private void doNeutronLoadBalancerCreate(NeutronLoadBalancer neutronLB) {
72 Preconditions.checkNotNull(loadBalancerProvider);
73 LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLB);
75 if (!lbConfig.isValid()) {
76 logger.trace("Neutron LB pool configuration invalid for {} ", lbConfig.getName());
78 for (Node node: this.switchManager.getNodes())
79 loadBalancerProvider.programLoadBalancerRules(node, lbConfig, Action.ADD);
84 public int canUpdateNeutronLoadBalancer(NeutronLoadBalancer delta, NeutronLoadBalancer original) {
85 return HttpURLConnection.HTTP_OK;
89 public void neutronLoadBalancerUpdated(NeutronLoadBalancer neutronLB) {
90 enqueueEvent(new NorthboundEvent(neutronLB, Action.UPDATE));
95 public int canDeleteNeutronLoadBalancer(NeutronLoadBalancer neutronLB) {
96 LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLB);
97 if (!lbConfig.isValid())
98 return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
100 return HttpURLConnection.HTTP_OK;
104 public void neutronLoadBalancerDeleted(NeutronLoadBalancer neutronLB) {
105 logger.debug("Neutron LB Deletion : {}", neutronLB.toString());
106 enqueueEvent(new NorthboundEvent(neutronLB, Action.DELETE));
109 private void doNeutronLoadBalancerDelete(NeutronLoadBalancer neutronLB) {
110 Preconditions.checkNotNull(loadBalancerProvider);
111 LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLB);
113 if (!lbConfig.isValid()) {
114 logger.trace("Neutron LB pool configuration invalid for {} ", lbConfig.getName());
116 for (Node node: this.switchManager.getNodes())
117 loadBalancerProvider.programLoadBalancerRules(node, lbConfig, Action.DELETE);
124 * @param abstractEvent the {@link org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent} event to be handled.
125 * @see org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher
128 public void processEvent(AbstractEvent abstractEvent) {
129 if (!(abstractEvent instanceof NorthboundEvent)) {
130 logger.error("Unable to process abstract event " + abstractEvent);
133 NorthboundEvent ev = (NorthboundEvent) abstractEvent;
134 switch (ev.getAction()) {
136 doNeutronLoadBalancerCreate(ev.getLoadBalancer());
138 doNeutronLoadBalancerDelete(ev.getLoadBalancer());
141 * Currently member update requires delete and re-adding
142 * Also, weights and weight updates are not supported
144 doNeutronLoadBalancerDelete(ev.getLoadBalancer());
145 doNeutronLoadBalancerCreate(ev.getLoadBalancer());
148 logger.warn("Unable to process event action " + ev.getAction());
154 * Useful utility for extracting the loadbalancer instance
155 * configuration from the neutron LB cache
157 public LoadBalancerConfiguration extractLBConfiguration(NeutronLoadBalancer neutronLB) {
158 String loadBalancerName = neutronLB.getLoadBalancerName();
159 String loadBalancerVip = neutronLB.getLoadBalancerVipAddress();
160 String loadBalancerSubnetID = neutronLB.getLoadBalancerVipSubnetID();
161 LoadBalancerConfiguration lbConfig = new LoadBalancerConfiguration(loadBalancerName, loadBalancerVip);
163 String memberID, memberIP, memberMAC, memberProtocol;
166 for (NeutronLoadBalancerPool neutronLBPool: neutronLBPoolCache.getAllNeutronLoadBalancerPools()) {
167 List<? extends NeutronLoadBalancerPoolMember> members =
168 (List<? extends NeutronLoadBalancerPoolMember>)neutronLBPool.getLoadBalancerPoolMembers();
169 memberProtocol = neutronLBPool.getLoadBalancerPoolProtocol();
171 * Only HTTP and HTTPS are supported as of this version
172 * TODO: Support all TCP load-balancers
174 if (!(memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
175 memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTPS)))
177 for (NeutronLoadBalancerPoolMember neutronLBPoolMember: members) {
178 if (neutronLBPoolMember.getPoolMemberSubnetID().equals(loadBalancerSubnetID) &&
179 neutronLBPoolMember.getPoolMemberAdminStateIsUp()) {
180 memberID = neutronLBPoolMember.getPoolMemberID();
181 memberIP = neutronLBPoolMember.getPoolMemberAddress();
182 memberPort = neutronLBPoolMember.getPoolMemberProtoPort();
183 memberMAC = NeutronCacheUtils.getMacAddress(neutronPortsCache, memberIP);
184 if (memberMAC == null)
186 lbConfig.addMember(memberID, memberIP, memberMAC, memberProtocol, memberPort);