You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mu...@apache.org on 2012/06/25 18:23:57 UTC
[2/3] moving out F5 code from server into plugins/network-elements/f5/
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/422c4ce5/plugins/network-elements/f5/src/com/cloud/api/commands/ListF5LoadBalancerNetworksCmd.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/f5/src/com/cloud/api/commands/ListF5LoadBalancerNetworksCmd.java b/plugins/network-elements/f5/src/com/cloud/api/commands/ListF5LoadBalancerNetworksCmd.java
new file mode 100644
index 0000000..efa71b5
--- /dev/null
+++ b/plugins/network-elements/f5/src/com/cloud/api/commands/ListF5LoadBalancerNetworksCmd.java
@@ -0,0 +1,94 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License. Citrix Systems, Inc.
+// reserves all rights not expressly granted by the License.
+// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.api.ApiConstants;
+import com.cloud.api.BaseCmd;
+import com.cloud.api.BaseListCmd;
+import com.cloud.api.IdentityMapper;
+import com.cloud.api.Implementation;
+import com.cloud.api.Parameter;
+import com.cloud.api.PlugService;
+import com.cloud.api.ServerApiException;
+import com.cloud.api.response.ListResponse;
+import com.cloud.api.response.NetworkResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.Network;
+import com.cloud.network.element.F5ExternalLoadBalancerElementService;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@Implementation(responseObject=NetworkResponse.class, description="lists network that are using a F5 load balancer device")
+public class ListF5LoadBalancerNetworksCmd extends BaseListCmd {
+
+ public static final Logger s_logger = Logger.getLogger(ListF5LoadBalancerNetworksCmd.class.getName());
+ private static final String s_name = "listf5loadbalancernetworksresponse";
+ @PlugService F5ExternalLoadBalancerElementService _f5DeviceManagerService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @IdentityMapper(entityTableName="external_load_balancer_devices")
+ @Parameter(name=ApiConstants.LOAD_BALANCER_DEVICE_ID, type=CommandType.LONG, required = true, description="f5 load balancer device ID")
+ private Long lbDeviceId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getLoadBalancerDeviceId() {
+ return lbDeviceId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException {
+ try {
+ List<? extends Network> networks = _f5DeviceManagerService.listNetworks(this);
+ ListResponse<NetworkResponse> response = new ListResponse<NetworkResponse>();
+ List<NetworkResponse> networkResponses = new ArrayList<NetworkResponse>();
+
+ if (networks != null && !networks.isEmpty()) {
+ for (Network network : networks) {
+ NetworkResponse networkResponse = _responseGenerator.createNetworkResponse(network);
+ networkResponses.add(networkResponse);
+ }
+ }
+
+ response.setResponses(networkResponses);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } catch (InvalidParameterValueException invalidParamExcp) {
+ throw new ServerApiException(BaseCmd.PARAM_ERROR, invalidParamExcp.getMessage());
+ } catch (CloudRuntimeException runtimeExcp) {
+ throw new ServerApiException(BaseCmd.INTERNAL_ERROR, runtimeExcp.getMessage());
+ }
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/422c4ce5/plugins/network-elements/f5/src/com/cloud/api/commands/ListF5LoadBalancersCmd.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/f5/src/com/cloud/api/commands/ListF5LoadBalancersCmd.java b/plugins/network-elements/f5/src/com/cloud/api/commands/ListF5LoadBalancersCmd.java
new file mode 100644
index 0000000..228bab5
--- /dev/null
+++ b/plugins/network-elements/f5/src/com/cloud/api/commands/ListF5LoadBalancersCmd.java
@@ -0,0 +1,101 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License. Citrix Systems, Inc.
+// reserves all rights not expressly granted by the License.
+// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.api.ApiConstants;
+import com.cloud.api.BaseCmd;
+import com.cloud.api.BaseListCmd;
+import com.cloud.api.IdentityMapper;
+import com.cloud.api.Implementation;
+import com.cloud.api.Parameter;
+import com.cloud.api.PlugService;
+import com.cloud.api.ServerApiException;
+import com.cloud.api.response.F5LoadBalancerResponse;
+import com.cloud.api.response.ListResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.ExternalLoadBalancerDeviceVO;
+import com.cloud.network.element.F5ExternalLoadBalancerElementService;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@Implementation(responseObject=F5LoadBalancerResponse.class, description="lists F5 load balancer devices")
+public class ListF5LoadBalancersCmd extends BaseListCmd {
+ public static final Logger s_logger = Logger.getLogger(ListF5LoadBalancersCmd.class.getName());
+ private static final String s_name = "listf5loadbalancerresponse";
+ @PlugService F5ExternalLoadBalancerElementService _f5DeviceManagerService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @IdentityMapper(entityTableName="physical_network")
+ @Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.LONG, description="the Physical Network ID")
+ private Long physicalNetworkId;
+
+ @IdentityMapper(entityTableName="external_load_balancer_devices")
+ @Parameter(name=ApiConstants.LOAD_BALANCER_DEVICE_ID, type=CommandType.LONG, description="f5 load balancer device ID")
+ private Long lbDeviceId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getLoadBalancerDeviceId() {
+ return lbDeviceId;
+ }
+
+ public Long getPhysicalNetworkId() {
+ return physicalNetworkId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException {
+ try {
+ List<ExternalLoadBalancerDeviceVO> lbDevices = _f5DeviceManagerService.listF5LoadBalancers(this);
+ ListResponse<F5LoadBalancerResponse> response = new ListResponse<F5LoadBalancerResponse>();
+ List<F5LoadBalancerResponse> lbDevicesResponse = new ArrayList<F5LoadBalancerResponse>();
+
+ if (lbDevices != null && !lbDevices.isEmpty()) {
+ for (ExternalLoadBalancerDeviceVO lbDeviceVO : lbDevices) {
+ F5LoadBalancerResponse lbdeviceResponse = _f5DeviceManagerService.createF5LoadBalancerResponse(lbDeviceVO);
+ lbDevicesResponse.add(lbdeviceResponse);
+ }
+ }
+
+ response.setResponses(lbDevicesResponse);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } catch (InvalidParameterValueException invalidParamExcp) {
+ throw new ServerApiException(BaseCmd.PARAM_ERROR, invalidParamExcp.getMessage());
+ } catch (CloudRuntimeException runtimeExcp) {
+ throw new ServerApiException(BaseCmd.INTERNAL_ERROR, runtimeExcp.getMessage());
+ }
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/422c4ce5/plugins/network-elements/f5/src/com/cloud/api/response/F5LoadBalancerResponse.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/f5/src/com/cloud/api/response/F5LoadBalancerResponse.java b/plugins/network-elements/f5/src/com/cloud/api/response/F5LoadBalancerResponse.java
new file mode 100644
index 0000000..dbb962f
--- /dev/null
+++ b/plugins/network-elements/f5/src/com/cloud/api/response/F5LoadBalancerResponse.java
@@ -0,0 +1,101 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.api.response;
+
+import com.cloud.api.ApiConstants;
+import com.cloud.utils.IdentityProxy;
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+public class F5LoadBalancerResponse extends BaseResponse {
+ @SerializedName(ApiConstants.LOAD_BALANCER_DEVICE_ID) @Param(description="device id of the F5 load balancer")
+ private IdentityProxy id = new IdentityProxy("external_load_balancer_devices");
+
+ @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @Param(description="the physical network to which this F5 device belongs to")
+ private IdentityProxy physicalNetworkId = new IdentityProxy("physical_network");
+
+ @SerializedName(ApiConstants.PROVIDER) @Param(description="name of the provider")
+ private String providerName;
+
+ @SerializedName(ApiConstants.LOAD_BALANCER_DEVICE_NAME) @Param(description="device name")
+ private String deviceName;
+
+ @SerializedName(ApiConstants.LOAD_BALANCER_DEVICE_STATE) @Param(description="device state")
+ private String deviceState;
+
+ @SerializedName(ApiConstants.LOAD_BALANCER_DEVICE_CAPACITY) @Param(description="device capacity")
+ private Long deviceCapacity;
+
+ @SerializedName(ApiConstants.LOAD_BALANCER_DEVICE_DEDICATED) @Param(description="true if device is dedicated for an account")
+ private Boolean dedicatedLoadBalancer;
+
+ @SerializedName(ApiConstants.INLINE) @Param(description="true if device is inline with firewall device")
+ private Boolean inlineLoadBalancer;
+
+ @SerializedName(ApiConstants.PUBLIC_INTERFACE) @Param(description="the public interface of the load balancer")
+ private String publicInterface;
+
+ @SerializedName(ApiConstants.PRIVATE_INTERFACE) @Param(description="the private interface of the load balancer")
+ private String privateInterface;
+
+ @SerializedName(ApiConstants.IP_ADDRESS) @Param(description="the management IP address of the external load balancer")
+ private String ipAddress;
+
+ public void setId(long lbDeviceId) {
+ this.id.setValue(lbDeviceId);
+ }
+
+ public void setPhysicalNetworkId(long physicalNetworkId) {
+ this.physicalNetworkId.setValue(physicalNetworkId);
+ }
+
+ public void setProvider(String provider) {
+ this.providerName = provider;
+ }
+
+ public void setDeviceName(String deviceName) {
+ this.deviceName = deviceName;
+ }
+
+ public void setDeviceCapacity(long deviceCapacity) {
+ this.deviceCapacity = deviceCapacity;
+ }
+
+ public void setDeviceState(String deviceState) {
+ this.deviceState = deviceState;
+ }
+
+ public void setDedicatedLoadBalancer(boolean isDedicated) {
+ this.dedicatedLoadBalancer = isDedicated;
+ }
+
+ public void setInlineMode(boolean inline) {
+ this.inlineLoadBalancer = inline;
+ }
+
+ public void setPublicInterface(String publicInterface) {
+ this.publicInterface = publicInterface;
+ }
+
+ public void setPrivateInterface(String privateInterface) {
+ this.privateInterface = privateInterface;
+ }
+
+ public void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/422c4ce5/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java
new file mode 100644
index 0000000..1b1cbf7
--- /dev/null
+++ b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java
@@ -0,0 +1,470 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License. Citrix Systems, Inc.
+// reserves all rights not expressly granted by the License.
+// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.network.element;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ejb.Local;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.api.commands.AddExternalLoadBalancerCmd;
+import com.cloud.api.commands.AddF5LoadBalancerCmd;
+import com.cloud.api.commands.ConfigureF5LoadBalancerCmd;
+import com.cloud.api.commands.DeleteExternalLoadBalancerCmd;
+import com.cloud.api.commands.DeleteF5LoadBalancerCmd;
+import com.cloud.api.commands.ListExternalLoadBalancersCmd;
+import com.cloud.api.commands.ListF5LoadBalancerNetworksCmd;
+import com.cloud.api.commands.ListF5LoadBalancersCmd;
+import com.cloud.api.response.F5LoadBalancerResponse;
+import com.cloud.configuration.Config;
+import com.cloud.configuration.ConfigurationManager;
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InsufficientNetworkCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.host.dao.HostDetailsDao;
+import com.cloud.network.ExternalLoadBalancerDeviceManager;
+import com.cloud.network.ExternalLoadBalancerDeviceManagerImpl;
+import com.cloud.network.ExternalLoadBalancerDeviceVO;
+import com.cloud.network.ExternalLoadBalancerDeviceVO.LBDeviceState;
+import com.cloud.network.ExternalNetworkDeviceManager.NetworkDevice;
+import com.cloud.network.Network;
+import com.cloud.network.Network.Capability;
+import com.cloud.network.Network.Provider;
+import com.cloud.network.Network.Service;
+import com.cloud.network.NetworkExternalLoadBalancerVO;
+import com.cloud.network.NetworkManager;
+import com.cloud.network.NetworkVO;
+import com.cloud.network.Networks.TrafficType;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.PhysicalNetworkVO;
+import com.cloud.network.PublicIpAddress;
+import com.cloud.network.dao.ExternalLoadBalancerDeviceDao;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkExternalLoadBalancerDao;
+import com.cloud.network.dao.NetworkServiceMapDao;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.lb.LoadBalancingRule;
+import com.cloud.network.resource.F5BigIpResource;
+import com.cloud.network.rules.LbStickinessMethod;
+import com.cloud.network.rules.LbStickinessMethod.StickinessMethodType;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.resource.ServerResource;
+import com.cloud.server.api.response.ExternalLoadBalancerResponse;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.component.Inject;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
+import com.google.gson.Gson;
+
+@Local(value = NetworkElement.class)
+public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceManagerImpl implements LoadBalancingServiceProvider, IpDeployer, F5ExternalLoadBalancerElementService, ExternalLoadBalancerDeviceManager {
+
+ private static final Logger s_logger = Logger.getLogger(F5ExternalLoadBalancerElement.class);
+
+ @Inject
+ NetworkManager _networkManager;
+ @Inject
+ ConfigurationManager _configMgr;
+ @Inject
+ NetworkServiceMapDao _ntwkSrvcDao;
+ @Inject
+ DataCenterDao _dcDao;
+ @Inject
+ PhysicalNetworkDao _physicalNetworkDao;
+ @Inject
+ HostDao _hostDao;
+ @Inject
+ ExternalLoadBalancerDeviceDao _lbDeviceDao;
+ @Inject
+ NetworkExternalLoadBalancerDao _networkLBDao;
+ @Inject
+ NetworkDao _networkDao;
+ @Inject
+ HostDetailsDao _detailsDao;
+ @Inject
+ ConfigurationDao _configDao;
+
+ private boolean canHandle(Network config) {
+ if (config.getGuestType() != Network.GuestType.Isolated || config.getTrafficType() != TrafficType.Guest) {
+ s_logger.trace("Not handling network with Type " + config.getGuestType() + " and traffic type " + config.getTrafficType());
+ return false;
+ }
+
+ return (_networkManager.isProviderForNetwork(getProvider(), config.getId()) && _ntwkSrvcDao.canProviderSupportServiceInNetwork(config.getId(), Service.Lb, Network.Provider.F5BigIp));
+ }
+
+ @Override
+ public boolean implement(Network guestConfig, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException, ConcurrentOperationException,
+ InsufficientNetworkCapacityException {
+
+ if (!canHandle(guestConfig)) {
+ return false;
+ }
+
+ try {
+ return manageGuestNetworkWithExternalLoadBalancer(true, guestConfig);
+ } catch (InsufficientCapacityException capacityException) {
+ throw new ResourceUnavailableException("There are no F5 load balancer devices with the free capacity for implementing this network", DataCenter.class, guestConfig.getDataCenterId());
+ }
+ }
+
+ @Override
+ public boolean prepare(Network config, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException,
+ InsufficientNetworkCapacityException, ResourceUnavailableException {
+ return true;
+ }
+
+ @Override
+ public boolean release(Network config, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, ReservationContext context) {
+ return true;
+ }
+
+ @Override
+ public boolean shutdown(Network guestConfig, ReservationContext context, boolean cleanup) throws ResourceUnavailableException, ConcurrentOperationException {
+ if (!canHandle(guestConfig)) {
+ return false;
+ }
+
+ try {
+ return manageGuestNetworkWithExternalLoadBalancer(false, guestConfig);
+ } catch (InsufficientCapacityException capacityException) {
+ // TODO: handle out of capacity exception
+ return false;
+ }
+ }
+
+ @Override
+ public boolean destroy(Network config) {
+ return true;
+ }
+
+ @Override
+ public boolean validateLBRule(Network network, LoadBalancingRule rule) {
+ return true;
+ }
+
+ @Override
+ public boolean applyLBRules(Network config, List<LoadBalancingRule> rules) throws ResourceUnavailableException {
+ if (!canHandle(config)) {
+ return false;
+ }
+
+ return applyLoadBalancerRules(config, rules);
+ }
+
+ @Override
+ public Map<Service, Map<Capability, String>> getCapabilities() {
+ Map<Service, Map<Capability, String>> capabilities = new HashMap<Service, Map<Capability, String>>();
+
+ // Set capabilities for LB service
+ Map<Capability, String> lbCapabilities = new HashMap<Capability, String>();
+
+ // Specifies that the RoundRobin and Leastconn algorithms are supported for load balancing rules
+ lbCapabilities.put(Capability.SupportedLBAlgorithms, "roundrobin,leastconn");
+
+ // specifies that F5 BIG IP network element can provide shared mode only
+ lbCapabilities.put(Capability.SupportedLBIsolation, "dedicated, shared");
+
+ // Specifies that load balancing rules can be made for either TCP or UDP traffic
+ lbCapabilities.put(Capability.SupportedProtocols, "tcp,udp");
+
+ // Specifies that this element can measure network usage on a per public IP basis
+ lbCapabilities.put(Capability.TrafficStatistics, "per public ip");
+
+ // Specifies that load balancing rules can only be made with public IPs that aren't source NAT IPs
+ lbCapabilities.put(Capability.LoadBalancingSupportedIps, "additional");
+
+ LbStickinessMethod method;
+ List<LbStickinessMethod> methodList = new ArrayList<LbStickinessMethod>();
+ method = new LbStickinessMethod(StickinessMethodType.LBCookieBased, "This is cookie based sticky method, can be used only for http");
+ methodList.add(method);
+ method.addParam("holdtime", false, "time period (in seconds) for which persistence is in effect.", false);
+
+ Gson gson = new Gson();
+ String stickyMethodList = gson.toJson(methodList);
+ lbCapabilities.put(Capability.SupportedStickinessMethods, stickyMethodList);
+
+ capabilities.put(Service.Lb, lbCapabilities);
+
+ return capabilities;
+ }
+
+ @Override
+ public Provider getProvider() {
+ return Provider.F5BigIp;
+ }
+
+ @Override
+ public boolean isReady(PhysicalNetworkServiceProvider provider) {
+ List<ExternalLoadBalancerDeviceVO> lbDevices = _lbDeviceDao.listByPhysicalNetworkAndProvider(provider.getPhysicalNetworkId(), Provider.F5BigIp.getName());
+
+ // true if at-least one F5 device is added in to physical network and is in configured (in enabled state) state
+ if (lbDevices != null && !lbDevices.isEmpty()) {
+ for (ExternalLoadBalancerDeviceVO lbDevice : lbDevices) {
+ if (lbDevice.getState() == LBDeviceState.Enabled) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
+ ResourceUnavailableException {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ @Override
+ public boolean canEnableIndividualServices() {
+ return false;
+ }
+
+ @Override
+ public String getPropertiesFile() {
+ return "f5bigip_commands.properties";
+ }
+
+ @Override
+ @Deprecated
+ public Host addExternalLoadBalancer(AddExternalLoadBalancerCmd cmd) {
+ Long zoneId = cmd.getZoneId();
+ DataCenterVO zone = null;
+ PhysicalNetworkVO pNetwork = null;
+ ExternalLoadBalancerDeviceVO lbDeviceVO = null;
+ HostVO lbHost = null;
+
+ zone = _dcDao.findById(zoneId);
+ if (zone == null) {
+ throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId);
+ }
+
+ List<PhysicalNetworkVO> physicalNetworks = _physicalNetworkDao.listByZone(zoneId);
+ if ((physicalNetworks == null) || (physicalNetworks.size() > 1)) {
+ throw new InvalidParameterValueException("There are no physical networks or multiple physical networks configured in zone with ID: "
+ + zoneId + " to add this device.");
+ }
+ pNetwork = physicalNetworks.get(0);
+
+ String deviceType = NetworkDevice.F5BigIpLoadBalancer.getName();
+ lbDeviceVO = addExternalLoadBalancer(pNetwork.getId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), deviceType, (ServerResource) new F5BigIpResource());
+
+ if (lbDeviceVO != null) {
+ lbHost = _hostDao.findById(lbDeviceVO.getHostId());
+ }
+
+ return lbHost;
+ }
+
+ @Override
+ @Deprecated
+ public boolean deleteExternalLoadBalancer(DeleteExternalLoadBalancerCmd cmd) {
+ return deleteExternalLoadBalancer(cmd.getId());
+ }
+
+ @Override
+ @Deprecated
+ public List<Host> listExternalLoadBalancers(ListExternalLoadBalancersCmd cmd) {
+ Long zoneId = cmd.getZoneId();
+ DataCenterVO zone = null;
+ PhysicalNetworkVO pNetwork = null;
+
+ if (zoneId != null) {
+ zone = _dcDao.findById(zoneId);
+ if (zone == null) {
+ throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId);
+ }
+
+ List<PhysicalNetworkVO> physicalNetworks = _physicalNetworkDao.listByZone(zoneId);
+ if ((physicalNetworks == null) || (physicalNetworks.size() > 1)) {
+ throw new InvalidParameterValueException("There are no physical networks or multiple physical networks configured in zone with ID: "
+ + zoneId + " to add this device.");
+ }
+ pNetwork = physicalNetworks.get(0);
+ return listExternalLoadBalancers(pNetwork.getId(), NetworkDevice.F5BigIpLoadBalancer.getName());
+ } else {
+ throw new InvalidParameterValueException("Zone Id must be specified to list the external load balancers");
+ }
+ }
+
+ @Override
+ @Deprecated
+ public ExternalLoadBalancerResponse createExternalLoadBalancerResponse(Host externalLb) {
+ return super.createExternalLoadBalancerResponse(externalLb);
+ }
+
+ @Override
+ public ExternalLoadBalancerDeviceVO addF5LoadBalancer(AddF5LoadBalancerCmd cmd) {
+ String deviceName = cmd.getDeviceType();
+ if (!deviceName.equalsIgnoreCase(NetworkDevice.F5BigIpLoadBalancer.getName())) {
+ throw new InvalidParameterValueException("Invalid F5 load balancer device type");
+ }
+
+ return addExternalLoadBalancer(cmd.getPhysicalNetworkId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), deviceName, (ServerResource) new F5BigIpResource());
+
+ }
+
+ @Override
+ public boolean deleteF5LoadBalancer(DeleteF5LoadBalancerCmd cmd) {
+ Long lbDeviceId = cmd.getLoadBalancerDeviceId();
+
+ ExternalLoadBalancerDeviceVO lbDeviceVo = _lbDeviceDao.findById(lbDeviceId);
+ if ((lbDeviceVo == null) || !lbDeviceVo.getDeviceName().equalsIgnoreCase(NetworkDevice.F5BigIpLoadBalancer.getName())) {
+ throw new InvalidParameterValueException("No F5 load balancer device found with ID: " + lbDeviceId);
+ }
+
+ return deleteExternalLoadBalancer(lbDeviceVo.getHostId());
+ }
+
+ @Override
+ public ExternalLoadBalancerDeviceVO configureF5LoadBalancer(ConfigureF5LoadBalancerCmd cmd) {
+ Long lbDeviceId = cmd.getLoadBalancerDeviceId();
+ Long capacity = cmd.getLoadBalancerCapacity();
+
+ ExternalLoadBalancerDeviceVO lbDeviceVo = _lbDeviceDao.findById(lbDeviceId);
+ if ((lbDeviceVo == null) || !lbDeviceVo.getDeviceName().equalsIgnoreCase(NetworkDevice.F5BigIpLoadBalancer.getName())) {
+ throw new InvalidParameterValueException("No F5 load balancer device found with ID: " + lbDeviceId);
+ }
+
+ if (capacity != null) {
+ // check if any networks are using this F5 device
+ List<NetworkExternalLoadBalancerVO> networks = _networkLBDao.listByLoadBalancerDeviceId(lbDeviceId);
+ if ((networks != null) && !networks.isEmpty()) {
+ if (capacity < networks.size()) {
+ throw new CloudRuntimeException("There are more number of networks already using this F5 device than configured capacity");
+ }
+ }
+ if (capacity != null) {
+ lbDeviceVo.setCapacity(capacity);
+ }
+ }
+
+ lbDeviceVo.setState(LBDeviceState.Enabled);
+ _lbDeviceDao.update(lbDeviceId, lbDeviceVo);
+ return lbDeviceVo;
+ }
+
+ @Override
+ public List<ExternalLoadBalancerDeviceVO> listF5LoadBalancers(ListF5LoadBalancersCmd cmd) {
+ Long physcialNetworkId = cmd.getPhysicalNetworkId();
+ Long lbDeviceId = cmd.getLoadBalancerDeviceId();
+ PhysicalNetworkVO pNetwork = null;
+ List<ExternalLoadBalancerDeviceVO> lbDevices = new ArrayList<ExternalLoadBalancerDeviceVO>();
+
+ if (physcialNetworkId == null && lbDeviceId == null) {
+ throw new InvalidParameterValueException("Either physical network Id or load balancer device Id must be specified");
+ }
+
+ if (lbDeviceId != null) {
+ ExternalLoadBalancerDeviceVO lbDeviceVo = _lbDeviceDao.findById(lbDeviceId);
+ if (lbDeviceVo == null || !lbDeviceVo.getDeviceName().equalsIgnoreCase(NetworkDevice.F5BigIpLoadBalancer.getName())) {
+ throw new InvalidParameterValueException("Could not find F5 load balancer device with ID: " + lbDeviceId);
+ }
+ lbDevices.add(lbDeviceVo);
+ return lbDevices;
+ }
+
+ if (physcialNetworkId != null) {
+ pNetwork = _physicalNetworkDao.findById(physcialNetworkId);
+ if (pNetwork == null) {
+ throw new InvalidParameterValueException("Could not find phyical network with ID: " + physcialNetworkId);
+ }
+ lbDevices = _lbDeviceDao.listByPhysicalNetworkAndProvider(physcialNetworkId, Provider.F5BigIp.getName());
+ return lbDevices;
+ }
+
+ return null;
+ }
+
+ @Override
+ public List<? extends Network> listNetworks(ListF5LoadBalancerNetworksCmd cmd) {
+ Long lbDeviceId = cmd.getLoadBalancerDeviceId();
+ List<NetworkVO> networks = new ArrayList<NetworkVO>();
+
+ ExternalLoadBalancerDeviceVO lbDeviceVo = _lbDeviceDao.findById(lbDeviceId);
+ if (lbDeviceVo == null || !lbDeviceVo.getDeviceName().equalsIgnoreCase(NetworkDevice.F5BigIpLoadBalancer.getName())) {
+ throw new InvalidParameterValueException("Could not find F5 load balancer device with ID " + lbDeviceId);
+ }
+
+ List<NetworkExternalLoadBalancerVO> networkLbMaps = _networkLBDao.listByLoadBalancerDeviceId(lbDeviceId);
+ if (networkLbMaps != null && !networkLbMaps.isEmpty()) {
+ for (NetworkExternalLoadBalancerVO networkLbMap : networkLbMaps) {
+ NetworkVO network = _networkDao.findById(networkLbMap.getNetworkId());
+ networks.add(network);
+ }
+ }
+
+ return networks;
+ }
+
+ @Override
+ public F5LoadBalancerResponse createF5LoadBalancerResponse(ExternalLoadBalancerDeviceVO lbDeviceVO) {
+ F5LoadBalancerResponse response = new F5LoadBalancerResponse();
+ Host lbHost = _hostDao.findById(lbDeviceVO.getHostId());
+ Map<String, String> lbDetails = _detailsDao.findDetails(lbDeviceVO.getHostId());
+
+ response.setId(lbDeviceVO.getId());
+ response.setIpAddress(lbHost.getPrivateIpAddress());
+ response.setPhysicalNetworkId(lbDeviceVO.getPhysicalNetworkId());
+ response.setPublicInterface(lbDetails.get("publicInterface"));
+ response.setPrivateInterface(lbDetails.get("privateInterface"));
+ response.setDeviceName(lbDeviceVO.getDeviceName());
+ if (lbDeviceVO.getCapacity() == 0) {
+ long defaultLbCapacity = NumbersUtil.parseLong(_configDao.getValue(Config.DefaultExternalLoadBalancerCapacity.key()), 50);
+ response.setDeviceCapacity(defaultLbCapacity);
+ } else {
+ response.setDeviceCapacity(lbDeviceVO.getCapacity());
+ }
+ response.setInlineMode(lbDeviceVO.getIsInLineMode());
+ response.setDedicatedLoadBalancer(lbDeviceVO.getIsDedicatedDevice());
+ response.setProvider(lbDeviceVO.getProviderName());
+ response.setDeviceState(lbDeviceVO.getState().name());
+ response.setObjectName("f5loadbalancer");
+ return response;
+ }
+
+ @Override
+ public boolean verifyServicesCombination(List<String> services) {
+ return true;
+ }
+
+ @Override
+ public boolean applyIps(Network network, List<? extends PublicIpAddress> ipAddress, Set<Service> service) throws ResourceUnavailableException {
+ // return true, as IP will be associated as part of LB rule configuration
+ return false;
+ }
+
+ @Override
+ public IpDeployer getIpDeployer(Network network) {
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/422c4ce5/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElementService.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElementService.java b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElementService.java
new file mode 100644
index 0000000..ee288ef
--- /dev/null
+++ b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElementService.java
@@ -0,0 +1,84 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License. Citrix Systems, Inc.
+// reserves all rights not expressly granted by the License.
+// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.network.element;
+
+import java.util.List;
+
+import com.cloud.api.commands.AddExternalLoadBalancerCmd;
+import com.cloud.api.commands.AddF5LoadBalancerCmd;
+import com.cloud.api.commands.ConfigureF5LoadBalancerCmd;
+import com.cloud.api.commands.DeleteExternalLoadBalancerCmd;
+import com.cloud.api.commands.DeleteF5LoadBalancerCmd;
+import com.cloud.api.commands.ListExternalLoadBalancersCmd;
+import com.cloud.api.commands.ListF5LoadBalancerNetworksCmd;
+import com.cloud.api.commands.ListF5LoadBalancersCmd;
+import com.cloud.api.response.F5LoadBalancerResponse;
+import com.cloud.host.Host;
+import com.cloud.network.ExternalLoadBalancerDeviceVO;
+import com.cloud.network.Network;
+import com.cloud.server.api.response.ExternalLoadBalancerResponse;
+import com.cloud.utils.component.PluggableService;
+
+@SuppressWarnings("deprecation")
+public interface F5ExternalLoadBalancerElementService extends PluggableService {
+
+ /**
+ * adds a F5 load balancer device in to a physical network
+ * @param AddF5LoadBalancerCmd
+ * @return ExternalLoadBalancerDeviceVO object for the device added
+ */
+ public ExternalLoadBalancerDeviceVO addF5LoadBalancer(AddF5LoadBalancerCmd cmd);
+
+ /**
+ * removes a F5 load balancer device from a physical network
+ * @param DeleteF5LoadBalancerCmd
+ * @return true if F5 load balancer device is successfully deleted
+ */
+ public boolean deleteF5LoadBalancer(DeleteF5LoadBalancerCmd cmd);
+
+ /**
+ * configures a F5 load balancer device added in a physical network
+ * @param ConfigureF5LoadBalancerCmd
+ * @return ExternalLoadBalancerDeviceVO for the device configured
+ */
+ public ExternalLoadBalancerDeviceVO configureF5LoadBalancer(ConfigureF5LoadBalancerCmd cmd);
+
+ /**
+ * lists all the load balancer devices added in to a physical network
+ * @param ListF5LoadBalancersCmd
+ * @return list of ExternalLoadBalancerDeviceVO for the devices in the physical network.
+ */
+ public List<ExternalLoadBalancerDeviceVO> listF5LoadBalancers(ListF5LoadBalancersCmd cmd);
+
+ /**
+ * lists all the guest networks using a F5 load balancer device
+ * @param ListF5LoadBalancerNetworksCmd
+ * @return list of the guest networks that are using this F5 load balancer
+ */
+ public List<? extends Network> listNetworks(ListF5LoadBalancerNetworksCmd cmd);
+
+ public F5LoadBalancerResponse createF5LoadBalancerResponse(ExternalLoadBalancerDeviceVO lbDeviceVO);
+
+ /* Deprecated API helper function */
+ @Deprecated // API helper function supported for backward compatibility
+ public Host addExternalLoadBalancer(AddExternalLoadBalancerCmd cmd);
+
+ @Deprecated // API helper function supported for backward compatibility
+ public boolean deleteExternalLoadBalancer(DeleteExternalLoadBalancerCmd cmd);
+
+ @Deprecated // API helper function supported for backward compatibility
+ public List<Host> listExternalLoadBalancers(ListExternalLoadBalancersCmd cmd);
+
+ @Deprecated // API helper function supported for backward compatibility
+ public ExternalLoadBalancerResponse createExternalLoadBalancerResponse(Host externalLb);
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/422c4ce5/plugins/network-elements/f5/src/com/cloud/network/resource/F5BigIpResource.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/f5/src/com/cloud/network/resource/F5BigIpResource.java b/plugins/network-elements/f5/src/com/cloud/network/resource/F5BigIpResource.java
new file mode 100644
index 0000000..501656f
--- /dev/null
+++ b/plugins/network-elements/f5/src/com/cloud/network/resource/F5BigIpResource.java
@@ -0,0 +1,1081 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License. Citrix Systems, Inc.
+// reserves all rights not expressly granted by the License.
+// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.network.resource;
+
+import iControl.CommonEnabledState;
+import iControl.CommonIPPortDefinition;
+import iControl.CommonStatistic;
+import iControl.CommonStatisticType;
+import iControl.CommonVirtualServerDefinition;
+import iControl.Interfaces;
+import iControl.LocalLBLBMethod;
+import iControl.LocalLBNodeAddressBindingStub;
+import iControl.LocalLBPersistenceMode;
+import iControl.LocalLBPoolBindingStub;
+import iControl.LocalLBProfileContextType;
+import iControl.LocalLBProfilePersistenceBindingStub;
+import iControl.LocalLBProfileULong;
+import iControl.LocalLBVirtualServerBindingStub;
+import iControl.LocalLBVirtualServerVirtualServerPersistence;
+import iControl.LocalLBVirtualServerVirtualServerProfile;
+import iControl.LocalLBVirtualServerVirtualServerResource;
+import iControl.LocalLBVirtualServerVirtualServerStatisticEntry;
+import iControl.LocalLBVirtualServerVirtualServerStatistics;
+import iControl.LocalLBVirtualServerVirtualServerType;
+import iControl.NetworkingMemberTagType;
+import iControl.NetworkingMemberType;
+import iControl.NetworkingRouteDomainBindingStub;
+import iControl.NetworkingSelfIPBindingStub;
+import iControl.NetworkingVLANBindingStub;
+import iControl.NetworkingVLANMemberEntry;
+import iControl.SystemConfigSyncBindingStub;
+import iControl.SystemConfigSyncSaveMode;
+
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.IAgentControl;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer;
+import com.cloud.agent.api.ExternalNetworkResourceUsageCommand;
+import com.cloud.agent.api.MaintainAnswer;
+import com.cloud.agent.api.MaintainCommand;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.ReadyAnswer;
+import com.cloud.agent.api.ReadyCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupExternalLoadBalancerCommand;
+import com.cloud.agent.api.routing.IpAssocAnswer;
+import com.cloud.agent.api.routing.IpAssocCommand;
+import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
+import com.cloud.agent.api.routing.NetworkElementCommand;
+import com.cloud.agent.api.to.IpAddressTO;
+import com.cloud.agent.api.to.LoadBalancerTO;
+import com.cloud.agent.api.to.LoadBalancerTO.DestinationTO;
+import com.cloud.agent.api.to.LoadBalancerTO.StickinessPolicyTO;
+import com.cloud.host.Host;
+import com.cloud.network.rules.LbStickinessMethod.StickinessMethodType;
+import com.cloud.resource.ServerResource;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.Pair;
+import com.cloud.utils.exception.ExecutionException;
+import com.cloud.utils.net.NetUtils;
+
+public class F5BigIpResource implements ServerResource {
+
+ private enum LbAlgorithm {
+ RoundRobin(null, LocalLBLBMethod.LB_METHOD_ROUND_ROBIN),
+ LeastConn(null, LocalLBLBMethod.LB_METHOD_LEAST_CONNECTION_MEMBER);
+
+ String persistenceProfileName;
+ LocalLBLBMethod method;
+
+ LbAlgorithm(String persistenceProfileName, LocalLBLBMethod method) {
+ this.persistenceProfileName = persistenceProfileName;
+ this.method = method;
+ }
+
+ public String getPersistenceProfileName() {
+ return persistenceProfileName;
+ }
+
+ public LocalLBLBMethod getMethod() {
+ return method;
+ }
+ }
+
+ private enum LbProtocol {
+ tcp,
+ udp;
+ }
+
+ private String _name;
+ private String _zoneId;
+ private String _ip;
+ private String _username;
+ private String _password;
+ private String _publicInterface;
+ private String _privateInterface;
+ private Integer _numRetries;
+ private String _guid;
+ private boolean _inline;
+
+ private Interfaces _interfaces;
+ private LocalLBVirtualServerBindingStub _virtualServerApi;
+ private LocalLBPoolBindingStub _loadbalancerApi;
+ private LocalLBNodeAddressBindingStub _nodeApi;
+ private NetworkingVLANBindingStub _vlanApi;
+ private NetworkingSelfIPBindingStub _selfIpApi;
+ private NetworkingRouteDomainBindingStub _routeDomainApi;
+ private SystemConfigSyncBindingStub _configSyncApi;
+ private LocalLBProfilePersistenceBindingStub _persistenceProfileApi;
+ private String _objectNamePathSep = "-";
+ private String _routeDomainIdentifier = "%";
+
+ private static final Logger s_logger = Logger.getLogger(F5BigIpResource.class);
+
+ @Override
+ public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+ try {
+ XTrustProvider.install();
+
+ _name = (String) params.get("name");
+ if (_name == null) {
+ throw new ConfigurationException("Unable to find name");
+ }
+
+ _zoneId = (String) params.get("zoneId");
+ if (_zoneId == null) {
+ throw new ConfigurationException("Unable to find zone");
+ }
+
+ _ip = (String) params.get("ip");
+ if (_ip == null) {
+ throw new ConfigurationException("Unable to find IP");
+ }
+
+ _username = (String) params.get("username");
+ if (_username == null) {
+ throw new ConfigurationException("Unable to find username");
+ }
+
+ _password = (String) params.get("password");
+ if (_password == null) {
+ throw new ConfigurationException("Unable to find password");
+ }
+
+ _publicInterface = (String) params.get("publicinterface");
+ if (_publicInterface == null) {
+ throw new ConfigurationException("Unable to find public interface");
+ }
+
+ _privateInterface = (String) params.get("privateinterface");
+ if (_privateInterface == null) {
+ throw new ConfigurationException("Unable to find private interface");
+ }
+
+ _numRetries = NumbersUtil.parseInt((String) params.get("numretries"), 1);
+
+ _guid = (String)params.get("guid");
+ if (_guid == null) {
+ throw new ConfigurationException("Unable to find the guid");
+ }
+
+ _inline = Boolean.parseBoolean((String) params.get("inline"));
+
+ login();
+
+ return true;
+ } catch (Exception e) {
+ throw new ConfigurationException(e.getMessage());
+ }
+
+ }
+
+ @Override
+ public StartupCommand[] initialize() {
+ StartupExternalLoadBalancerCommand cmd = new StartupExternalLoadBalancerCommand();
+ cmd.setName(_name);
+ cmd.setDataCenter(_zoneId);
+ cmd.setPod("");
+ cmd.setPrivateIpAddress(_ip);
+ cmd.setStorageIpAddress("");
+ cmd.setVersion("");
+ cmd.setGuid(_guid);
+ return new StartupCommand[]{cmd};
+ }
+
+ @Override
+ public Host.Type getType() {
+ return Host.Type.ExternalLoadBalancer;
+ }
+
+ @Override
+ public String getName() {
+ return _name;
+ }
+
+ @Override
+ public PingCommand getCurrentStatus(final long id) {
+ return new PingCommand(Host.Type.ExternalLoadBalancer, id);
+ }
+
+ @Override
+ public boolean start() {
+ return true;
+ }
+
+ @Override
+ public boolean stop() {
+ return true;
+ }
+
+ @Override
+ public void disconnected() {
+ return;
+ }
+
+ @Override
+ public IAgentControl getAgentControl() {
+ return null;
+ }
+
+ @Override
+ public void setAgentControl(IAgentControl agentControl) {
+ return;
+ }
+
+ @Override
+ public Answer executeRequest(Command cmd) {
+ return executeRequest(cmd, _numRetries);
+ }
+
+ private Answer executeRequest(Command cmd, int numRetries) {
+ if (cmd instanceof ReadyCommand) {
+ return execute((ReadyCommand) cmd);
+ } else if (cmd instanceof MaintainCommand) {
+ return execute((MaintainCommand) cmd);
+ } else if (cmd instanceof IpAssocCommand) {
+ return execute((IpAssocCommand) cmd, numRetries);
+ } else if (cmd instanceof LoadBalancerConfigCommand) {
+ return execute((LoadBalancerConfigCommand) cmd, numRetries);
+ } else if (cmd instanceof ExternalNetworkResourceUsageCommand) {
+ return execute((ExternalNetworkResourceUsageCommand) cmd);
+ } else {
+ return Answer.createUnsupportedCommandAnswer(cmd);
+ }
+ }
+
+ private Answer retry(Command cmd, int numRetries) {
+ int numRetriesRemaining = numRetries - 1;
+ s_logger.error("Retrying " + cmd.getClass().getSimpleName() + ". Number of retries remaining: " + numRetriesRemaining);
+ return executeRequest(cmd, numRetriesRemaining);
+ }
+
+ private boolean shouldRetry(int numRetries) {
+ try {
+ if (numRetries > 0) {
+ login();
+ return true;
+ }
+ } catch (Exception e) {
+ s_logger.error("Failed to log in to F5 device at " + _ip + " due to " + e.getMessage());
+ }
+ return false;
+ }
+
+ private Answer execute(ReadyCommand cmd) {
+ return new ReadyAnswer(cmd);
+ }
+
+ private Answer execute(MaintainCommand cmd) {
+ return new MaintainAnswer(cmd);
+ }
+
+ private synchronized Answer execute(IpAssocCommand cmd, int numRetries) {
+ String[] results = new String[cmd.getIpAddresses().length];
+ int i = 0;
+ try {
+ IpAddressTO[] ips = cmd.getIpAddresses();
+ for (IpAddressTO ip : ips) {
+ long guestVlanTag = Long.valueOf(ip.getVlanId());
+ String vlanSelfIp = _inline ? tagAddressWithRouteDomain(ip.getVlanGateway(), guestVlanTag) : ip.getVlanGateway();
+ String vlanNetmask = ip.getVlanNetmask();
+
+ // Delete any existing guest VLAN with this tag, self IP, and netmask
+ deleteGuestVlan(guestVlanTag, vlanSelfIp, vlanNetmask);
+
+ if (ip.isAdd()) {
+ // Add a new guest VLAN
+ addGuestVlan(guestVlanTag, vlanSelfIp, vlanNetmask);
+ }
+
+ saveConfiguration();
+ results[i++] = ip.getPublicIp() + " - success";
+ }
+
+ } catch (ExecutionException e) {
+ s_logger.error("Failed to execute IPAssocCommand due to " + e);
+
+ if (shouldRetry(numRetries)) {
+ return retry(cmd, numRetries);
+ } else {
+ results[i++] = IpAssocAnswer.errorResult;
+ }
+ }
+
+ return new IpAssocAnswer(cmd, results);
+ }
+
+ private synchronized Answer execute(LoadBalancerConfigCommand cmd, int numRetries) {
+ try {
+ long guestVlanTag = Long.parseLong(cmd.getAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG));
+ LoadBalancerTO[] loadBalancers = cmd.getLoadBalancers();
+ for (LoadBalancerTO loadBalancer : loadBalancers) {
+ LbProtocol lbProtocol;
+ try {
+ if (loadBalancer.getProtocol() == null) {
+ lbProtocol = LbProtocol.tcp;
+ } else {
+ lbProtocol = LbProtocol.valueOf(loadBalancer.getProtocol());
+ }
+ } catch (IllegalArgumentException e) {
+ throw new ExecutionException("Got invalid protocol: " + loadBalancer.getProtocol());
+ }
+
+ LbAlgorithm lbAlgorithm;
+ if (loadBalancer.getAlgorithm().equals("roundrobin")) {
+ lbAlgorithm = LbAlgorithm.RoundRobin;
+ } else if (loadBalancer.getAlgorithm().equals("leastconn")) {
+ lbAlgorithm = LbAlgorithm.LeastConn;
+ } else {
+ throw new ExecutionException("Got invalid algorithm: " + loadBalancer.getAlgorithm());
+ }
+
+ String srcIp = _inline ? tagAddressWithRouteDomain(loadBalancer.getSrcIp(), guestVlanTag) : loadBalancer.getSrcIp();
+ int srcPort = loadBalancer.getSrcPort();
+ String virtualServerName = genVirtualServerName(lbProtocol, srcIp, srcPort);
+
+ boolean destinationsToAdd = false;
+ for (DestinationTO destination : loadBalancer.getDestinations()) {
+ if (!destination.isRevoked()) {
+ destinationsToAdd = true;
+ break;
+ }
+ }
+
+ if (!loadBalancer.isRevoked() && destinationsToAdd) {
+ // Add the pool
+ addPool(virtualServerName, lbAlgorithm);
+
+ // Add pool members
+ List<String> activePoolMembers = new ArrayList<String>();
+ for (DestinationTO destination : loadBalancer.getDestinations()) {
+ if (!destination.isRevoked()) {
+ String destIp = _inline ? tagAddressWithRouteDomain(destination.getDestIp(), guestVlanTag) : destination.getDestIp();
+ addPoolMember(virtualServerName, destIp, destination.getDestPort());
+ activePoolMembers.add(destIp + "-" + destination.getDestPort());
+ }
+ }
+
+ // Delete any pool members that aren't in the current list of destinations
+ deleteInactivePoolMembers(virtualServerName, activePoolMembers);
+
+ // Add the virtual server
+ addVirtualServer(virtualServerName, lbProtocol, srcIp, srcPort, loadBalancer.getStickinessPolicies());
+ } else {
+ // Delete the virtual server with this protocol, source IP, and source port, along with its default pool and all pool members
+ deleteVirtualServerAndDefaultPool(virtualServerName);
+ }
+ }
+
+ saveConfiguration();
+ return new Answer(cmd);
+ } catch (ExecutionException e) {
+ s_logger.error("Failed to execute LoadBalancerConfigCommand due to " + e);
+
+ if (shouldRetry(numRetries)) {
+ return retry(cmd, numRetries);
+ } else {
+ return new Answer(cmd, e);
+ }
+
+ }
+ }
+
+ private synchronized ExternalNetworkResourceUsageAnswer execute(ExternalNetworkResourceUsageCommand cmd) {
+ try {
+ return getIpBytesSentAndReceived(cmd);
+ } catch (ExecutionException e) {
+ return new ExternalNetworkResourceUsageAnswer(cmd, e);
+ }
+ }
+
+ private void saveConfiguration() throws ExecutionException {
+ try {
+ _configSyncApi.save_configuration("", SystemConfigSyncSaveMode.SAVE_BASE_LEVEL_CONFIG);
+ _configSyncApi.save_configuration("", SystemConfigSyncSaveMode.SAVE_HIGH_LEVEL_CONFIG);
+ s_logger.debug("Successfully saved F5 BigIp configuration.");
+ } catch (RemoteException e) {
+ s_logger.error("Failed to save F5 BigIp configuration due to: " + e);
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private void addGuestVlan(long vlanTag, String vlanSelfIp, String vlanNetmask) throws ExecutionException {
+ try {
+ String vlanName = genVlanName(vlanTag);
+ List<String> allVlans = getVlans();
+ if (!allVlans.contains(vlanName)) {
+ String[] vlanNames = genStringArray(vlanName);
+ long[] vlanTags = genLongArray(vlanTag);
+ CommonEnabledState[] commonEnabledState = {CommonEnabledState.STATE_DISABLED};
+
+ // Create the interface name
+ NetworkingVLANMemberEntry[][] vlanMemberEntries = {{new NetworkingVLANMemberEntry()}};
+ vlanMemberEntries[0][0].setMember_type(NetworkingMemberType.MEMBER_INTERFACE);
+ vlanMemberEntries[0][0].setTag_state(NetworkingMemberTagType.MEMBER_TAGGED);
+ vlanMemberEntries[0][0].setMember_name(_privateInterface);
+
+ s_logger.debug("Creating a guest VLAN with tag " + vlanTag);
+ _vlanApi.create(vlanNames, vlanTags, vlanMemberEntries, commonEnabledState, new long[]{10L}, new String[]{"00:00:00:00:00:00"});
+
+ if (!getVlans().contains(vlanName)) {
+ throw new ExecutionException("Failed to create vlan with tag " + vlanTag);
+ }
+ }
+
+ if (_inline) {
+ List<Long> allRouteDomains = getRouteDomains();
+ if (!allRouteDomains.contains(vlanTag)) {
+ long[] routeDomainIds = genLongArray(vlanTag);
+ String[][] vlanNames = new String[][]{genStringArray(genVlanName(vlanTag))};
+
+ s_logger.debug("Creating route domain " + vlanTag);
+ _routeDomainApi.create(routeDomainIds, vlanNames);
+
+ if (!getRouteDomains().contains(vlanTag)) {
+ throw new ExecutionException("Failed to create route domain " + vlanTag);
+ }
+ }
+ }
+
+ List<String> allSelfIps = getSelfIps();
+ if (!allSelfIps.contains(vlanSelfIp)) {
+ String[] selfIpsToCreate = genStringArray(vlanSelfIp);
+ String[] vlans = genStringArray(vlanName);
+ String[] netmasks = genStringArray(vlanNetmask);
+ long[] unitIds = genLongArray(0L);
+ CommonEnabledState[] enabledStates = new CommonEnabledState[]{CommonEnabledState.STATE_DISABLED};
+
+ s_logger.debug("Creating self IP " + vlanSelfIp);
+ _selfIpApi.create(selfIpsToCreate, vlans, netmasks, unitIds, enabledStates);
+
+ if (!getSelfIps().contains(vlanSelfIp)) {
+ throw new ExecutionException("Failed to create self IP " + vlanSelfIp);
+ }
+ }
+ } catch (RemoteException e) {
+ s_logger.error(e);
+ throw new ExecutionException(e.getMessage());
+ }
+
+ }
+
+ private void deleteGuestVlan(long vlanTag, String vlanSelfIp, String vlanNetmask) throws ExecutionException {
+ try {
+ // Delete all virtual servers and pools that use this guest VLAN
+ deleteVirtualServersInGuestVlan(vlanSelfIp, vlanNetmask);
+
+ List<String> allSelfIps = getSelfIps();
+ if (allSelfIps.contains(vlanSelfIp)) {
+ s_logger.debug("Deleting self IP " + vlanSelfIp);
+ _selfIpApi.delete_self_ip(genStringArray(vlanSelfIp));
+
+ if (getSelfIps().contains(vlanSelfIp)) {
+ throw new ExecutionException("Failed to delete self IP " + vlanSelfIp);
+ }
+ }
+
+ if (_inline) {
+ List<Long> allRouteDomains = getRouteDomains();
+ if (allRouteDomains.contains(vlanTag)) {
+ s_logger.debug("Deleting route domain " + vlanTag);
+ _routeDomainApi.delete_route_domain(genLongArray(vlanTag));
+
+ if (getRouteDomains().contains(vlanTag)) {
+ throw new ExecutionException("Failed to delete route domain " + vlanTag);
+ }
+ }
+ }
+
+ String vlanName = genVlanName(vlanTag);
+ List<String> allVlans = getVlans();
+ if (allVlans.contains(vlanName)) {
+ _vlanApi.delete_vlan(genStringArray(vlanName));
+
+ if (getVlans().contains(vlanName)) {
+ throw new ExecutionException("Failed to delete VLAN with tag: " + vlanTag);
+ }
+ }
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private void deleteVirtualServersInGuestVlan(String vlanSelfIp, String vlanNetmask) throws ExecutionException {
+ vlanSelfIp = stripRouteDomainFromAddress(vlanSelfIp);
+ List<String> virtualServersToDelete = new ArrayList<String>();
+
+ List<String> allVirtualServers = getVirtualServers();
+ for (String virtualServerName : allVirtualServers) {
+ // Check if the virtual server's default pool has members in this guest VLAN
+ List<String> poolMembers = getMembers(virtualServerName);
+ for (String poolMemberName : poolMembers) {
+ String poolMemberIp = stripRouteDomainFromAddress(getIpAndPort(poolMemberName)[0]);
+ if (NetUtils.sameSubnet(vlanSelfIp, poolMemberIp, vlanNetmask)) {
+ virtualServersToDelete.add(virtualServerName);
+ break;
+ }
+ }
+ }
+
+ for (String virtualServerName : virtualServersToDelete) {
+ s_logger.debug("Found a virtual server (" + virtualServerName + ") for guest network with self IP " + vlanSelfIp + " that is active when the guest network is being destroyed.");
+ deleteVirtualServerAndDefaultPool(virtualServerName);
+ }
+ }
+
+ private String genVlanName(long vlanTag) {
+ return "vlan-" + String.valueOf(vlanTag);
+ }
+
+ private List<Long> getRouteDomains() throws ExecutionException {
+ try {
+ List<Long> routeDomains = new ArrayList<Long>();
+ long[] routeDomainsArray = _routeDomainApi.get_list();
+
+ for (long routeDomainName : routeDomainsArray) {
+ routeDomains.add(routeDomainName);
+ }
+
+ return routeDomains;
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private List<String> getSelfIps() throws ExecutionException {
+ try {
+ List<String> selfIps = new ArrayList<String>();
+ String[] selfIpsArray = _selfIpApi.get_list();
+
+ for (String selfIp : selfIpsArray) {
+ selfIps.add(selfIp);
+ }
+
+ return selfIps;
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private List<String> getVlans() throws ExecutionException {
+ try {
+ List<String> vlans = new ArrayList<String>();
+ String[] vlansArray = _vlanApi.get_list();
+
+ for (String vlan : vlansArray) {
+ vlans.add(vlan);
+ }
+
+ return vlans;
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ // Login
+
+ private void login() throws ExecutionException {
+ try {
+ _interfaces = new Interfaces();
+
+ if (!_interfaces.initialize(_ip, _username, _password)) {
+ throw new ExecutionException("Failed to log in to BigIp appliance");
+ }
+
+ // iControl.Interfaces.initialize always return true so make a call to force connect to F5 to validate credentials
+ _interfaces.getSystemSystemInfo().get_system_information();
+
+ _virtualServerApi = _interfaces.getLocalLBVirtualServer();
+ _loadbalancerApi = _interfaces.getLocalLBPool();
+ _nodeApi = _interfaces.getLocalLBNodeAddress();
+ _vlanApi = _interfaces.getNetworkingVLAN();
+ _selfIpApi = _interfaces.getNetworkingSelfIP();
+ _routeDomainApi = _interfaces.getNetworkingRouteDomain();
+ _configSyncApi = _interfaces.getSystemConfigSync();
+ _persistenceProfileApi = _interfaces.getLocalLBProfilePersistence();
+ } catch (Exception e) {
+ throw new ExecutionException("Failed to log in to BigIp appliance due to " + e.getMessage());
+ }
+ }
+
+ // Virtual server methods
+
+ private void addVirtualServer(String virtualServerName, LbProtocol protocol, String srcIp, int srcPort, StickinessPolicyTO[] stickyPolicies) throws ExecutionException {
+ try {
+ if (!virtualServerExists(virtualServerName)) {
+ s_logger.debug("Adding virtual server " + virtualServerName);
+ _virtualServerApi.create(genVirtualServerDefinition(virtualServerName, protocol, srcIp, srcPort), new String[]{"255.255.255.255"}, genVirtualServerResource(virtualServerName), genVirtualServerProfile(protocol));
+ _virtualServerApi.set_snat_automap(genStringArray(virtualServerName));
+ if (!virtualServerExists(virtualServerName)) {
+ throw new ExecutionException("Failed to add virtual server " + virtualServerName);
+ }
+ }
+
+ if ((stickyPolicies != null) && (stickyPolicies.length > 0) && (stickyPolicies[0] != null)){
+ StickinessPolicyTO stickinessPolicy = stickyPolicies[0];
+ if (StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) {
+
+ String[] profileNames = genStringArray("Cookie-profile-" + virtualServerName);
+ if (!persistenceProfileExists(profileNames[0])) {
+ LocalLBPersistenceMode[] lbPersistenceMode = new iControl.LocalLBPersistenceMode[1];
+ lbPersistenceMode[0] = iControl.LocalLBPersistenceMode.PERSISTENCE_MODE_COOKIE;
+ _persistenceProfileApi.create(profileNames, lbPersistenceMode);
+ _virtualServerApi.add_persistence_profile(genStringArray(virtualServerName), genPersistenceProfile(profileNames[0]));
+ }
+
+ List<Pair<String, String>> paramsList = stickinessPolicy.getParams();
+ for(Pair<String,String> param : paramsList) {
+ if ("holdtime".equalsIgnoreCase(param.first())) {
+ long timeout = 180; //F5 default
+ if (param.second() != null) {
+ timeout = Long.parseLong(param.second());
+ }
+ LocalLBProfileULong[] cookieTimeout = new LocalLBProfileULong[1];
+ cookieTimeout[0] = new LocalLBProfileULong();
+ cookieTimeout[0].setValue(timeout);
+ _persistenceProfileApi.set_cookie_expiration(profileNames, cookieTimeout);
+ }
+ }
+ }
+ } else {
+ _virtualServerApi.remove_all_persistence_profiles(genStringArray(virtualServerName));
+ }
+
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private void deleteVirtualServerAndDefaultPool(String virtualServerName) throws ExecutionException {
+ try {
+ if (virtualServerExists(virtualServerName)) {
+ // Delete the default pool's members
+ List<String> poolMembers = getMembers(virtualServerName);
+ for (String poolMember : poolMembers) {
+ String[] destIpAndPort = getIpAndPort(poolMember);
+ deletePoolMember(virtualServerName, destIpAndPort[0], Integer.valueOf(destIpAndPort[1]));
+ }
+
+ // Delete the virtual server
+ s_logger.debug("Deleting virtual server " + virtualServerName);
+ _virtualServerApi.delete_virtual_server(genStringArray(virtualServerName));
+
+ if (getVirtualServers().contains(virtualServerName)) {
+ throw new ExecutionException("Failed to delete virtual server " + virtualServerName);
+ }
+
+ // Delete the default pool
+ deletePool(virtualServerName);
+ }
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private String genVirtualServerName(LbProtocol protocol, String srcIp, long srcPort) {
+ srcIp = stripRouteDomainFromAddress(srcIp);
+ return genObjectName("vs", protocol, srcIp, srcPort);
+ }
+
+ private boolean virtualServerExists(String virtualServerName) throws ExecutionException {
+ return getVirtualServers().contains(virtualServerName);
+ }
+
+ private List<String> getVirtualServers() throws ExecutionException {
+ try {
+ List<String> virtualServers = new ArrayList<String>();
+ String[] virtualServersArray = _virtualServerApi.get_list();
+
+ for (String virtualServer : virtualServersArray) {
+ virtualServers.add(virtualServer);
+ }
+
+ return virtualServers;
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private boolean persistenceProfileExists(String profileName) throws ExecutionException {
+ try {
+ String[] persistenceProfileArray = _persistenceProfileApi.get_list();
+ if (persistenceProfileArray == null) {
+ return false;
+ }
+ for (String profile: persistenceProfileArray) {
+ if (profile.equalsIgnoreCase(profileName)) {
+ return true;
+ }
+ }
+ return false;
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private iControl.CommonVirtualServerDefinition[] genVirtualServerDefinition(String name, LbProtocol protocol, String srcIp, long srcPort) {
+ CommonVirtualServerDefinition vsDefs[] = {new CommonVirtualServerDefinition()};
+ vsDefs[0].setName(name);
+ vsDefs[0].setAddress(srcIp);
+ vsDefs[0].setPort(srcPort);
+
+ if (protocol.equals(LbProtocol.tcp)) {
+ vsDefs[0].setProtocol(iControl.CommonProtocolType.PROTOCOL_TCP);
+ } else if (protocol.equals(LbProtocol.udp)) {
+ vsDefs[0].setProtocol(iControl.CommonProtocolType.PROTOCOL_UDP);
+ }
+
+ return vsDefs;
+ }
+
+ private iControl.LocalLBVirtualServerVirtualServerResource[] genVirtualServerResource(String poolName) {
+ LocalLBVirtualServerVirtualServerResource vsRes[] = {new LocalLBVirtualServerVirtualServerResource()};
+ vsRes[0].setType(LocalLBVirtualServerVirtualServerType.RESOURCE_TYPE_POOL);
+ vsRes[0].setDefault_pool_name(poolName);
+ return vsRes;
+ }
+
+ private LocalLBVirtualServerVirtualServerProfile[][] genVirtualServerProfile(LbProtocol protocol) {
+ LocalLBVirtualServerVirtualServerProfile vsProfs[][] = {{new LocalLBVirtualServerVirtualServerProfile()}};
+ vsProfs[0][0].setProfile_context(LocalLBProfileContextType.PROFILE_CONTEXT_TYPE_ALL);
+
+ if (protocol.equals(LbProtocol.tcp)) {
+ vsProfs[0][0].setProfile_name("http");
+ } else if (protocol.equals(LbProtocol.udp)) {
+ vsProfs[0][0].setProfile_name("udp");
+ }
+
+ return vsProfs;
+ }
+
+ private LocalLBVirtualServerVirtualServerPersistence[][] genPersistenceProfile(String persistenceProfileName) {
+ LocalLBVirtualServerVirtualServerPersistence[][] persistenceProfs = {{new LocalLBVirtualServerVirtualServerPersistence()}};
+ persistenceProfs[0][0].setDefault_profile(true);
+ persistenceProfs[0][0].setProfile_name(persistenceProfileName);
+ return persistenceProfs;
+ }
+
+ // Load balancing pool methods
+
+ private void addPool(String virtualServerName, LbAlgorithm algorithm) throws ExecutionException {
+ try {
+ if (!poolExists(virtualServerName)) {
+ if (algorithm.getPersistenceProfileName() != null) {
+ algorithm = LbAlgorithm.RoundRobin;
+ }
+
+ s_logger.debug("Adding pool for virtual server " + virtualServerName + " with algorithm " + algorithm);
+ _loadbalancerApi.create(genStringArray(virtualServerName), genLbMethod(algorithm), genEmptyMembersArray());
+
+ if (!poolExists(virtualServerName)) {
+ throw new ExecutionException("Failed to create new pool for virtual server " + virtualServerName);
+ }
+ }
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private void deletePool(String virtualServerName) throws ExecutionException {
+ try {
+ if (poolExists(virtualServerName) && getMembers(virtualServerName).size() == 0) {
+ s_logger.debug("Deleting pool for virtual server " + virtualServerName);
+ _loadbalancerApi.delete_pool(genStringArray(virtualServerName));
+
+ if (poolExists(virtualServerName)) {
+ throw new ExecutionException("Failed to delete pool for virtual server " + virtualServerName);
+ }
+ }
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private void addPoolMember(String virtualServerName, String destIp, int destPort) throws ExecutionException {
+ try {
+ String memberIdentifier = destIp + "-" + destPort;
+
+ if (poolExists(virtualServerName) && !memberExists(virtualServerName, memberIdentifier)) {
+ s_logger.debug("Adding member " + memberIdentifier + " into pool for virtual server " + virtualServerName);
+ _loadbalancerApi.add_member(genStringArray(virtualServerName), genMembers(destIp, destPort));
+
+ if (!memberExists(virtualServerName, memberIdentifier)) {
+ throw new ExecutionException("Failed to add new member " + memberIdentifier + " into pool for virtual server " + virtualServerName);
+ }
+ }
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private void deleteInactivePoolMembers(String virtualServerName, List<String> activePoolMembers) throws ExecutionException {
+ List<String> allPoolMembers = getMembers(virtualServerName);
+
+ for (String member : allPoolMembers) {
+ if (!activePoolMembers.contains(member)) {
+ String[] ipAndPort = member.split("-");
+ deletePoolMember(virtualServerName, ipAndPort[0], Integer.valueOf(ipAndPort[1]));
+ }
+ }
+ }
+
+ private void deletePoolMember(String virtualServerName, String destIp, int destPort) throws ExecutionException {
+ try {
+ String memberIdentifier = destIp + "-" + destPort;
+ List<String> lbPools = getAllLbPools();
+
+ if (lbPools.contains(virtualServerName) && memberExists(virtualServerName, memberIdentifier)) {
+ s_logger.debug("Deleting member " + memberIdentifier + " from pool for virtual server " + virtualServerName);
+ _loadbalancerApi.remove_member(genStringArray(virtualServerName), genMembers(destIp, destPort));
+
+ if (memberExists(virtualServerName, memberIdentifier)) {
+ throw new ExecutionException("Failed to delete member " + memberIdentifier + " from pool for virtual server " + virtualServerName);
+ }
+
+ if (nodeExists(destIp)) {
+ boolean nodeNeeded = false;
+ done:
+ for (String poolToCheck : lbPools) {
+ for (String memberInPool : getMembers(poolToCheck)) {
+ if (getIpAndPort(memberInPool)[0].equals(destIp)) {
+ nodeNeeded = true;
+ break done;
+ }
+ }
+ }
+
+ if (!nodeNeeded) {
+ s_logger.debug("Deleting node " + destIp);
+ _nodeApi.delete_node_address(genStringArray(destIp));
+
+ if (nodeExists(destIp)) {
+ throw new ExecutionException("Failed to delete node " + destIp);
+ }
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private boolean poolExists(String poolName) throws ExecutionException {
+ return getAllLbPools().contains(poolName);
+ }
+
+ private boolean memberExists(String poolName, String memberIdentifier) throws ExecutionException {
+ return getMembers(poolName).contains(memberIdentifier);
+ }
+
+ private boolean nodeExists(String destIp) throws RemoteException {
+ return getNodes().contains(destIp);
+ }
+
+ private String[] getIpAndPort(String memberIdentifier) {
+ return memberIdentifier.split("-");
+ }
+
+ public List<String> getAllLbPools() throws ExecutionException {
+ try {
+ List<String> lbPools = new ArrayList<String>();
+ String[] pools = _loadbalancerApi.get_list();
+
+ for (String pool : pools) {
+ lbPools.add(pool);
+ }
+
+ return lbPools;
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private List<String> getMembers(String virtualServerName) throws ExecutionException {
+ try {
+ List<String> members = new ArrayList<String>();
+ String[] virtualServerNames = genStringArray(virtualServerName);
+ CommonIPPortDefinition[] membersArray = _loadbalancerApi.get_member(virtualServerNames)[0];
+
+ for (CommonIPPortDefinition member : membersArray) {
+ members.add(member.getAddress() + "-" + member.getPort());
+ }
+
+ return members;
+ } catch (RemoteException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ private List<String> getNodes() throws RemoteException {
+ List<String> nodes = new ArrayList<String>();
+ String[] nodesArray = _nodeApi.get_list();
+
+ for (String node : nodesArray) {
+ nodes.add(node);
+ }
+
+ return nodes;
+ }
+
+ private iControl.CommonIPPortDefinition[][] genMembers(String destIp, long destPort) {
+ iControl.CommonIPPortDefinition[] membersInnerArray = new iControl.CommonIPPortDefinition[1];
+ membersInnerArray[0] = new iControl.CommonIPPortDefinition(destIp, destPort);
+ return new iControl.CommonIPPortDefinition[][]{membersInnerArray};
+ }
+
+ private iControl.CommonIPPortDefinition[][] genEmptyMembersArray() {
+ iControl.CommonIPPortDefinition[] membersInnerArray = new iControl.CommonIPPortDefinition[0];
+ return new iControl.CommonIPPortDefinition[][]{membersInnerArray};
+ }
+
+ private LocalLBLBMethod[] genLbMethod(LbAlgorithm algorithm) {
+ if (algorithm.getMethod() != null) {
+ return new LocalLBLBMethod[]{algorithm.getMethod()};
+ } else {
+ return new LocalLBLBMethod[]{LbAlgorithm.RoundRobin.getMethod()};
+ }
+ }
+
+ // Stats methods
+
+ private ExternalNetworkResourceUsageAnswer getIpBytesSentAndReceived(ExternalNetworkResourceUsageCommand cmd) throws ExecutionException {
+ ExternalNetworkResourceUsageAnswer answer = new ExternalNetworkResourceUsageAnswer(cmd);
+
+ try {
+
+ LocalLBVirtualServerVirtualServerStatistics stats = _virtualServerApi.get_all_statistics();
+ for (LocalLBVirtualServerVirtualServerStatisticEntry entry : stats.getStatistics()) {
+ String virtualServerIp = entry.getVirtual_server().getAddress();
+
+ if (_inline) {
+ virtualServerIp = stripRouteDomainFromAddress(virtualServerIp);
+ }
+
+ long[] bytesSentAndReceived = answer.ipBytes.get(virtualServerIp);
+
+ if (bytesSentAndReceived == null) {
+ bytesSentAndReceived = new long[]{0, 0};
+ }
+
+ for (CommonStatistic stat : entry.getStatistics()) {
+ int index;
+ if (stat.getType().equals(CommonStatisticType.STATISTIC_CLIENT_SIDE_BYTES_OUT)) {
+ // Add to the outgoing bytes
+ index = 0;
+ } else if (stat.getType().equals(CommonStatisticType.STATISTIC_CLIENT_SIDE_BYTES_IN)) {
+ // Add to the incoming bytes
+ index = 1;
+ } else {
+ continue;
+ }
+
+ long high = stat.getValue().getHigh();
+ long low = stat.getValue().getLow();
+ long full = getFullUsage(high, low);
+
+
+ bytesSentAndReceived[index] += full;
+ }
+
+ if (bytesSentAndReceived[0] >= 0 && bytesSentAndReceived[1] >= 0) {
+ answer.ipBytes.put(virtualServerIp, bytesSentAndReceived);
+ }
+ }
+ } catch (Exception e) {
+ s_logger.error(e);
+ throw new ExecutionException(e.getMessage());
+ }
+
+ return answer;
+ }
+
+ private long getFullUsage(long high, long low) {
+ Double full;
+ Double rollOver = new Double((double) 0x7fffffff);
+ rollOver = new Double(rollOver.doubleValue() + 1.0);
+
+ if (high >= 0) {
+ // shift left 32 bits and mask off new bits to 0's
+ full = new Double((high << 32 & 0xffff0000));
+ } else {
+ // mask off sign bits + shift left by 32 bits then add the sign bit back
+ full = new Double(((high & 0x7fffffff) << 32) + (0x80000000 << 32));
+ }
+
+ if (low >= 0) {
+ // add low to full and we're good
+ full = new Double(full.doubleValue() + (double) low);
+ } else {
+ // add full to low after masking off sign bits and adding 1 to the masked off low order value
+ full = new Double(full.doubleValue() + (double) ((low & 0x7fffffff)) + rollOver.doubleValue());
+ }
+
+ return full.longValue();
+ }
+
+
+
+ // Misc methods
+
+ private String tagAddressWithRouteDomain(String address, long vlanTag) {
+ return address + _routeDomainIdentifier + vlanTag;
+ }
+
+ private String stripRouteDomainFromAddress(String address) {
+ int i = address.indexOf(_routeDomainIdentifier);
+
+ if (i > 0) {
+ address = address.substring(0, i);
+ }
+
+ return address;
+ }
+
+ private String genObjectName(Object... args) {
+ String objectName = "";
+
+ for (int i = 0; i < args.length; i++) {
+ objectName += args[i];
+ if (i != args.length -1) {
+ objectName += _objectNamePathSep;
+ }
+ }
+
+ return objectName;
+ }
+
+ private long[] genLongArray(long l) {
+ return new long[]{l};
+ }
+
+ private static String[] genStringArray(String s) {
+ return new String[]{s};
+ }
+
+}
+
+
+
+
+
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/422c4ce5/plugins/network-elements/netscaler/.classpath
----------------------------------------------------------------------
diff --git a/plugins/network-elements/netscaler/.classpath b/plugins/network-elements/netscaler/.classpath
index 1c573a6..a3f5d12 100644
--- a/plugins/network-elements/netscaler/.classpath
+++ b/plugins/network-elements/netscaler/.classpath
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/api"/>
<classpathentry combineaccessrules="false" kind="src" path="/core"/>
<classpathentry combineaccessrules="false" kind="src" path="/server"/>
<classpathentry combineaccessrules="false" kind="src" path="/utils"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/deps"/>
<classpathentry kind="output" path="bin"/>
</classpath>
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/422c4ce5/server/src/com/cloud/api/commands/AddExternalLoadBalancerCmd.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/commands/AddExternalLoadBalancerCmd.java b/server/src/com/cloud/api/commands/AddExternalLoadBalancerCmd.java
deleted file mode 100644
index a8208ae..0000000
--- a/server/src/com/cloud/api/commands/AddExternalLoadBalancerCmd.java
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2012 Citrix Systems, Inc. Licensed under the
-// Apache License, Version 2.0 (the "License"); you may not use this
-// file except in compliance with the License. Citrix Systems, Inc.
-// reserves all rights not expressly granted by the License.
-// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// Automatically generated by addcopyright.py at 04/03/2012
-package com.cloud.api.commands;
-
-import org.apache.log4j.Logger;
-
-import com.cloud.api.ApiConstants;
-import com.cloud.api.BaseCmd;
-import com.cloud.api.IdentityMapper;
-import com.cloud.api.Implementation;
-import com.cloud.api.Parameter;
-import com.cloud.api.PlugService;
-import com.cloud.api.ServerApiException;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.host.Host;
-import com.cloud.network.element.F5ExternalLoadBalancerElementService;
-import com.cloud.server.api.response.ExternalLoadBalancerResponse;
-import com.cloud.user.Account;
-import com.cloud.utils.exception.CloudRuntimeException;
-
-@Implementation(description="Adds F5 external load balancer appliance.", responseObject = ExternalLoadBalancerResponse.class)
-@Deprecated // API supported only for backward compatibility.
-public class AddExternalLoadBalancerCmd extends BaseCmd {
- public static final Logger s_logger = Logger.getLogger(AddExternalLoadBalancerCmd.class.getName());
- private static final String s_name = "addexternalloadbalancerresponse";
-
- /////////////////////////////////////////////////////
- //////////////// API parameters /////////////////////
- /////////////////////////////////////////////////////
-
- @IdentityMapper(entityTableName="data_center")
- @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, required = true, description="Zone in which to add the external load balancer appliance.")
- private Long zoneId;
-
- @Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the external load balancer appliance.")
- private String url;
-
- @Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Username of the external load balancer appliance.")
- private String username;
-
- @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Password of the external load balancer appliance.")
- private String password;
-
- ///////////////////////////////////////////////////
- /////////////////// Accessors ///////////////////////
- /////////////////////////////////////////////////////
-
- public Long getZoneId() {
- return zoneId;
- }
-
- public String getUrl() {
- return url;
- }
-
- public String getUsername() {
- return username;
- }
-
- public String getPassword() {
- return password;
- }
-
- @PlugService
- F5ExternalLoadBalancerElementService _f5DeviceManagerService;
-
- /////////////////////////////////////////////////////
- /////////////// API Implementation///////////////////
- /////////////////////////////////////////////////////
-
- @Override
- public String getCommandName() {
- return s_name;
- }
-
- @Override
- public long getEntityOwnerId() {
- return Account.ACCOUNT_ID_SYSTEM;
- }
-
- @Override
- public void execute(){
- try {
- Host externalLoadBalancer = _f5DeviceManagerService.addExternalLoadBalancer(this);
- ExternalLoadBalancerResponse response = _f5DeviceManagerService.createExternalLoadBalancerResponse(externalLoadBalancer);
- response.setObjectName("externalloadbalancer");
- response.setResponseName(getCommandName());
- this.setResponseObject(response);
- } catch (InvalidParameterValueException ipve) {
- throw new ServerApiException(BaseCmd.PARAM_ERROR, ipve.getMessage());
- } catch (CloudRuntimeException cre) {
- throw new ServerApiException(BaseCmd.INTERNAL_ERROR, cre.getMessage());
- }
- }
-}
\ No newline at end of file