From 0b05badaaa3eafe249291e385b6b2fd7965d10da Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Tue, 15 Nov 2011 12:18:59 -0800 Subject: [PATCH] bug 11817: NAAS external network device support -made Netscaler, SRX, F5 network elements as pluggable service -added abstract load balancer device manager ExternaLoadBalancerDeviceManager -made both F5 and Netscaler pluggable service to extend ExternaLoadBalancerDeviceManager -added abstract firewall device manager ExternalFirewallDeviceManager -made SRX pluugable service to extende ExternalFirewallDeviceManager -added API's to configure and manage netscaler devices --- .../api/routing/CreateLBApplianceCommand.java | 36 + .../routing/DestroyLBApplianceCommand.java | 27 + api/src/com/cloud/api/ApiConstants.java | 9 +- .../commands/CreateNetworkOfferingCmd.java | 1 + .../NetscalerLoadBalancerResponse.java | 57 + api/src/com/cloud/event/EventTypes.java | 8 + .../tomcatconf/f5bigip_commands.properties.in | 7 + .../junipersrx_commands.properties.in | 7 + ...tscalerloadbalancer_commands.properties.in | 9 + .../resource/CreateLBApplianceAnswer.java | 29 + .../resource/DestroyLBApplianceAnswer.java | 28 + .../network/resource/NetscalerResource.java | 33 +- .../api/commands/AddExternalFirewallCmd.java | 125 +- .../commands/AddExternalLoadBalancerCmd.java | 125 +- .../commands/AddNetscalerLoadBalancerCmd.java | 135 ++ .../ConfigureNetscalerLoadBalancerCmd.java | 122 ++ .../commands/DeleteExternalFirewallCmd.java | 90 +- .../DeleteExternalLoadBalancerCmd.java | 91 +- .../DeleteNetscalerLoadBalancerCmd.java | 106 ++ .../commands/ListExternalFirewallsCmd.java | 16 +- .../ListExternalLoadBalancersCmd.java | 19 +- .../ListNetscalerLoadBalancerNetworksCmd.java | 82 + .../ListNetscalerLoadBalancersCmd.java | 108 ++ .../DefaultComponentLibrary.java | 9 + .../ExternalFirewallDeviceManager.java | 100 ++ .../ExternalFirewallDeviceManagerImpl.java | 613 +++++++ .../network/ExternalFirewallDeviceVO.java | 58 +- .../ExternalLoadBalancerDeviceManager.java | 100 ++ ...ExternalLoadBalancerDeviceManagerImpl.java | 1071 +++++++++++ .../network/ExternalLoadBalancerDeviceVO.java | 67 +- .../network/ExternalNetworkDeviceManager.java | 65 - .../ExternalNetworkDeviceManagerImpl.java | 1593 +---------------- .../network/NetworkExternalFirewallVO.java | 25 +- .../NetworkExternalLoadBalancerVO.java | 25 +- .../dao/ExternalFirewallDeviceDao.java | 35 +- .../dao/ExternalFirewallDeviceDaoImpl.java | 43 +- .../dao/ExternalLoadBalancerDeviceDao.java | 42 +- .../ExternalLoadBalancerDeviceDaoImpl.java | 54 +- .../dao/NetworkExternalFirewallDao.java | 12 + .../dao/NetworkExternalLoadBalancerDao.java | 14 +- .../NetworkExternalLoadBalancerDaoImpl.java | 2 +- .../F5ExternalLoadBalancerElement.java | 111 +- .../F5ExternalLoadBalancerElementService.java | 44 + .../JuniperSRXExternalFirewallElement.java | 107 +- .../JuniperSRXFirewallElementService.java | 25 + .../NetscalerExternalLoadBalancerElement.java | 231 ++- .../NetscalerLoadBalancerElementService.java | 75 + .../guru/ExternalGuestNetworkGuru.java | 35 +- setup/db/create-schema.sql | 34 +- 49 files changed, 3885 insertions(+), 1975 deletions(-) create mode 100644 api/src/com/cloud/agent/api/routing/CreateLBApplianceCommand.java create mode 100644 api/src/com/cloud/agent/api/routing/DestroyLBApplianceCommand.java create mode 100644 api/src/com/cloud/api/response/NetscalerLoadBalancerResponse.java create mode 100644 client/tomcatconf/f5bigip_commands.properties.in create mode 100644 client/tomcatconf/junipersrx_commands.properties.in create mode 100644 client/tomcatconf/netscalerloadbalancer_commands.properties.in create mode 100644 core/src/com/cloud/network/resource/CreateLBApplianceAnswer.java create mode 100644 core/src/com/cloud/network/resource/DestroyLBApplianceAnswer.java create mode 100644 server/src/com/cloud/api/commands/AddNetscalerLoadBalancerCmd.java create mode 100644 server/src/com/cloud/api/commands/ConfigureNetscalerLoadBalancerCmd.java create mode 100644 server/src/com/cloud/api/commands/DeleteNetscalerLoadBalancerCmd.java create mode 100644 server/src/com/cloud/api/commands/ListNetscalerLoadBalancerNetworksCmd.java create mode 100644 server/src/com/cloud/api/commands/ListNetscalerLoadBalancersCmd.java create mode 100644 server/src/com/cloud/network/ExternalFirewallDeviceManager.java create mode 100644 server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java create mode 100644 server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java create mode 100644 server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java create mode 100644 server/src/com/cloud/network/element/F5ExternalLoadBalancerElementService.java create mode 100644 server/src/com/cloud/network/element/JuniperSRXFirewallElementService.java create mode 100644 server/src/com/cloud/network/element/NetscalerLoadBalancerElementService.java diff --git a/api/src/com/cloud/agent/api/routing/CreateLBApplianceCommand.java b/api/src/com/cloud/agent/api/routing/CreateLBApplianceCommand.java new file mode 100644 index 00000000000..008db121201 --- /dev/null +++ b/api/src/com/cloud/agent/api/routing/CreateLBApplianceCommand.java @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.agent.api.routing; + +/** NetworkElementCommand to spin a VPX instance on the Netscaler SDX load balancer appliance */ + +//TODO: fill in Nitro API parameters + +public class CreateLBApplianceCommand extends NetworkElementCommand { + + String lbApplianceIP = null; + + public CreateLBApplianceCommand(String lbIp) { + this.lbApplianceIP = lbIp; + } + + String getLoadBalancerIP() { + return lbApplianceIP; + } +} diff --git a/api/src/com/cloud/agent/api/routing/DestroyLBApplianceCommand.java b/api/src/com/cloud/agent/api/routing/DestroyLBApplianceCommand.java new file mode 100644 index 00000000000..1acd9afb674 --- /dev/null +++ b/api/src/com/cloud/agent/api/routing/DestroyLBApplianceCommand.java @@ -0,0 +1,27 @@ +/** + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/** NetworkElementCommand to destroy a VPX instance on the Netscaler SDX load balancer appliance */ + +//TODO: fill in the Nitro API parameters required + +package com.cloud.agent.api.routing; + +public class DestroyLBApplianceCommand extends NetworkElementCommand { + +} diff --git a/api/src/com/cloud/api/ApiConstants.java b/api/src/com/cloud/api/ApiConstants.java index 2b10d22e447..efb9cc6fb01 100755 --- a/api/src/com/cloud/api/ApiConstants.java +++ b/api/src/com/cloud/api/ApiConstants.java @@ -304,5 +304,12 @@ public class ApiConstants { public static final String ACL_TYPE= "acltype"; public static final String IS_SOURCE_NAT_SHARED = "isshared"; public static final String SUBDOMAIN_ACCESS = "subdomainaccess"; - + public static final String LOAD_BALANCER_DEVICE_ID = "lbdeviceid"; + public static final String LOAD_BALANCER_DEVICE_NAME = "lbdevicename"; + public static final String LOAD_BALANCER_DEVICE_STATE = "lbdevicestate"; + public static final String LOAD_BALANCER_DEVICE_CAPACITY = "lbdevicecapacity"; + public static final String LOAD_BALANCER_DEVICE_DEDICATED = "lbdevicededicated"; + public static final String FIREWALL_DEVICE_ID = "fwdeviceid"; + public static final String FIREWALL_DEVICE_NAME = "fwdevicename"; + public static final String FIREWALL_DEVICE_STATE = "fwdevicestate"; } diff --git a/api/src/com/cloud/api/commands/CreateNetworkOfferingCmd.java b/api/src/com/cloud/api/commands/CreateNetworkOfferingCmd.java index f8c3d6c9a2a..a837f6d57f6 100644 --- a/api/src/com/cloud/api/commands/CreateNetworkOfferingCmd.java +++ b/api/src/com/cloud/api/commands/CreateNetworkOfferingCmd.java @@ -259,6 +259,7 @@ public class CreateNetworkOfferingCmd extends BaseCmd { if ((capability == null) || (capabilityName == null) || (capabilityValue == null) ) { throw new InvalidParameterValueException("Invalid capability:" + capabilityName + " capability value:" + capabilityValue); } + if (svc.equalsIgnoreCase(service.getName())) { capabilityMap.put(capability, capabilityValue); } diff --git a/api/src/com/cloud/api/response/NetscalerLoadBalancerResponse.java b/api/src/com/cloud/api/response/NetscalerLoadBalancerResponse.java new file mode 100644 index 00000000000..50911484278 --- /dev/null +++ b/api/src/com/cloud/api/response/NetscalerLoadBalancerResponse.java @@ -0,0 +1,57 @@ +package com.cloud.api.response; + +import com.cloud.api.ApiConstants; +import com.cloud.api.IdentityProxy; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +public class NetscalerLoadBalancerResponse extends BaseResponse { + + @SerializedName(ApiConstants.LOAD_BALANCER_DEVICE_ID) @Param(description="device id of the netscaler load balancer") + private IdentityProxy id = new IdentityProxy("external_load_balancer_devices"); + + @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @Param(description="the physical network to which this netscaler 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="device capacity") + private Boolean dedicatedLoadBalancer; + + 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 setDedicatedLoadBalancer(boolean isDedicated) { + this.dedicatedLoadBalancer = isDedicated; + } + public void setDeviceState(String deviceState) { + this.deviceState = deviceState; + } +} diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index e55f4441de3..629080e048c 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -234,4 +234,12 @@ public class EventTypes { public static final String EVENT_TRAFFIC_TYPE_DELETE = "TRAFFIC.TYPE.DELETE"; public static final String EVENT_TRAFFIC_TYPE_UPDATE = "TRAFFIC.TYPE.UPDATE"; + // external network device events + public static final String EVENT_EXTERAL_LB_DEVICE_ADD = "PHYSICAL.LOADBALANCER.ADD" ; + public static final String EVENT_EXTERAL_LB_DEVICE_DELETE = "PHYSICAL.LOADBALANCER.DELETE"; + public static final String EVENT_EXTERAL_LB_DEVICE_CONFIGURE = "PHYSICAL.LOADBALANCER.CONFIGURE"; + + public static final String EVENT_EXTERAL_FIREWALL_DEVICE_ADD = "PHYSICAL.FIREWALL.ADD" ; + public static final String EVENT_EXTERAL_FIREWALL_DEVICE_DELETE = "PHYSICAL.FIREWALL.DELETE"; + public static final String EVENT_EXTERAL_FIREWALL_DEVICE_CONFIGURE = "PHYSICAL.FIREWALL.CONFIGURE"; } diff --git a/client/tomcatconf/f5bigip_commands.properties.in b/client/tomcatconf/f5bigip_commands.properties.in new file mode 100644 index 00000000000..1370ad8bc44 --- /dev/null +++ b/client/tomcatconf/f5bigip_commands.properties.in @@ -0,0 +1,7 @@ +### bitmap of permissions at the end of each classname, 1 = ADMIN, 2 = RESOURCE_DOMAIN_ADMIN, 4 = DOMAIN_ADMIN, 8 = USER +### Please standardize naming conventions to camel-case (even for acronyms). + +#### f5 big ip load balancer commands +addExternalLoadBalancer = com.cloud.api.commands.AddExternalLoadBalancerCmd;7 +deleteExternalLoadBalancer = com.cloud.api.commands.DeleteExternalLoadBalancerCmd;7 +listExternalLoadBalancer = com.cloud.api.commands.ListExternalLoadBalancerCmd;7 diff --git a/client/tomcatconf/junipersrx_commands.properties.in b/client/tomcatconf/junipersrx_commands.properties.in new file mode 100644 index 00000000000..06c68cec757 --- /dev/null +++ b/client/tomcatconf/junipersrx_commands.properties.in @@ -0,0 +1,7 @@ +### bitmap of permissions at the end of each classname, 1 = ADMIN, 2 = RESOURCE_DOMAIN_ADMIN, 4 = DOMAIN_ADMIN, 8 = USER +### Please standardize naming conventions to camel-case (even for acronyms). + +#### juniper srx firewall commands +addExternalFirewall = com.cloud.api.commands.AddExternalFirewallCmd;7 +deleteExternalFirewall = com.cloud.api.commands.DeleteExternalFirewallCmd;7 +listExternalFirewall = com.cloud.api.commands.ListExternalFirewallCmd;7 diff --git a/client/tomcatconf/netscalerloadbalancer_commands.properties.in b/client/tomcatconf/netscalerloadbalancer_commands.properties.in new file mode 100644 index 00000000000..35030e70590 --- /dev/null +++ b/client/tomcatconf/netscalerloadbalancer_commands.properties.in @@ -0,0 +1,9 @@ +### bitmap of permissions at the end of each classname, 1 = ADMIN, 2 = RESOURCE_DOMAIN_ADMIN, 4 = DOMAIN_ADMIN, 8 = USER +### Please standardize naming conventions to camel-case (even for acronyms). + +#### netscaler load balancer commands +addNetscalerLoadBalancerCmd = com.cloud.api.commands.AddNetscalerLoadBalancerCmd;7 +deleteNetscalerLoadBalancerCmd = com.cloud.api.commands.DeleteNetscalerLoadBalancerCmd;7 +configureNetscalerLoadBalancerCmd = com.cloud.api.commands.ConfigureNetscalerLoadBalancerCmd;7 +listNetscalerLoadBalancersCmd = com.cloud.api.commands.ListNetscalerLoadBalancersCmd;7 +listNetscalerLoadBalancerNetworksCmd = com.cloud.api.commands.ListNetscalerLoadBalancerNetworksCmd;7 diff --git a/core/src/com/cloud/network/resource/CreateLBApplianceAnswer.java b/core/src/com/cloud/network/resource/CreateLBApplianceAnswer.java new file mode 100644 index 00000000000..b15aa74bdf2 --- /dev/null +++ b/core/src/com/cloud/network/resource/CreateLBApplianceAnswer.java @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.network.resource; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; + +public class CreateLBApplianceAnswer extends Answer { + public CreateLBApplianceAnswer(Command cmd, boolean success) { + + } + +} diff --git a/core/src/com/cloud/network/resource/DestroyLBApplianceAnswer.java b/core/src/com/cloud/network/resource/DestroyLBApplianceAnswer.java new file mode 100644 index 00000000000..d7f4f31af70 --- /dev/null +++ b/core/src/com/cloud/network/resource/DestroyLBApplianceAnswer.java @@ -0,0 +1,28 @@ +/** + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.network.resource; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; + +public class DestroyLBApplianceAnswer extends Answer { + public DestroyLBApplianceAnswer(Command cmd, boolean success) { + + } +} diff --git a/core/src/com/cloud/network/resource/NetscalerResource.java b/core/src/com/cloud/network/resource/NetscalerResource.java index 3eb7f559c0d..90d00d095cc 100644 --- a/core/src/com/cloud/network/resource/NetscalerResource.java +++ b/core/src/com/cloud/network/resource/NetscalerResource.java @@ -24,6 +24,8 @@ import javax.naming.ConfigurationException; import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.agent.api.routing.CreateLBApplianceCommand; +import com.cloud.agent.api.routing.DestroyLBApplianceCommand; import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer; import com.cloud.agent.api.ExternalNetworkResourceUsageCommand; import com.cloud.agent.api.MaintainAnswer; @@ -53,7 +55,6 @@ import com.citrix.netscaler.nitro.resource.base.base_response; import com.citrix.netscaler.nitro.exception.nitro_exception; import com.citrix.netscaler.nitro.resource.config.ns.nsconfig; import com.citrix.netscaler.nitro.resource.config.lb.lbvserver; -import com.citrix.netscaler.nitro.resource.config.basic.service; import com.citrix.netscaler.nitro.resource.config.network.*; import com.citrix.netscaler.nitro.resource.config.ns.*; import com.citrix.netscaler.nitro.resource.config.basic.server_service_binding; @@ -145,7 +146,7 @@ public class NetscalerResource implements ServerResource { _inline = Boolean.parseBoolean((String) params.get("inline")); - login(); + login(); enableNetScalerLoadBalancing(); return true; @@ -209,6 +210,10 @@ public class NetscalerResource implements ServerResource { return execute((LoadBalancerConfigCommand) cmd, numRetries); } else if (cmd instanceof ExternalNetworkResourceUsageCommand) { return execute((ExternalNetworkResourceUsageCommand) cmd); + } else if (cmd instanceof CreateLBApplianceCommand) { + return execute((CreateLBApplianceCommand) cmd, numRetries); + } else if (cmd instanceof DestroyLBApplianceCommand) { + return execute((DestroyLBApplianceCommand) cmd, numRetries); } else { return Answer.createUnsupportedCommandAnswer(cmd); } @@ -223,6 +228,10 @@ public class NetscalerResource implements ServerResource { } private synchronized Answer execute(IpAssocCommand cmd, int numRetries) { + if (_isSdx) { + return Answer.createUnsupportedCommandAnswer(cmd); + } + String[] results = new String[cmd.getIpAddresses().length]; int i = 0; try { @@ -257,7 +266,11 @@ public class NetscalerResource implements ServerResource { } private synchronized Answer execute(LoadBalancerConfigCommand cmd, int numRetries) { - try { + try { + if (_isSdx) { + return Answer.createUnsupportedCommandAnswer(cmd); + } + String lbProtocol; String lbMethod; LoadBalancerTO[] loadBalancers = cmd.getLoadBalancers(); @@ -440,6 +453,18 @@ public class NetscalerResource implements ServerResource { } } + private synchronized Answer execute(CreateLBApplianceCommand cmd, int numRetries) { + assert(_isSdx) : "CreateLBApplianceCommand can only be sent to SDX device"; + // FIXME: use nitro API to spin a new VPX instance on SDX + return new CreateLBApplianceAnswer(cmd, true); + } + + private synchronized Answer execute(DestroyLBApplianceCommand cmd, int numRetries) { + assert(_isSdx) : "DestroyLBApplianceCommand can only be sent to SDX device"; + // FIXME: use nitro API to destroy VPX instance on SDX + return new DestroyLBApplianceAnswer(cmd, true); + } + private synchronized ExternalNetworkResourceUsageAnswer execute(ExternalNetworkResourceUsageCommand cmd) { try { return getPublicIpBytesSentAndReceived(cmd); @@ -733,7 +758,7 @@ public class NetscalerResource implements ServerResource { return answer; } - private Answer retry(Command cmd, int numRetries) { + 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); diff --git a/server/src/com/cloud/api/commands/AddExternalFirewallCmd.java b/server/src/com/cloud/api/commands/AddExternalFirewallCmd.java index 0e080f49381..26845c9b719 100644 --- a/server/src/com/cloud/api/commands/AddExternalFirewallCmd.java +++ b/server/src/com/cloud/api/commands/AddExternalFirewallCmd.java @@ -26,89 +26,88 @@ 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.api.BaseCmd.CommandType; import com.cloud.exception.InvalidParameterValueException; import com.cloud.host.Host; -import com.cloud.network.ExternalNetworkDeviceManager; -import com.cloud.server.ManagementService; +import com.cloud.network.element.JuniperSRXFirewallElementService; import com.cloud.server.api.response.ExternalFirewallResponse; import com.cloud.user.Account; -import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.exception.CloudRuntimeException; @Implementation(description="Adds an external firewall appliance", responseObject = ExternalFirewallResponse.class) public class AddExternalFirewallCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AddExternalFirewallCmd.class.getName()); - private static final String s_name = "addexternalfirewallresponse"; - - ///////////////////////////////////////////////////// + public static final Logger s_logger = Logger.getLogger(AddExternalFirewallCmd.class.getName()); + private static final String s_name = "addexternalfirewallresponse"; + + ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - + @IdentityMapper(entityTableName="data_center") - @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, required = true, description="Zone in which to add the external firewall appliance.") - private Long zoneId; + @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, required = true, description="Zone in which to add the external firewall appliance.") + private Long zoneId; - @Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the external firewall appliance.") - private String url; - - @Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Username of the external firewall appliance.") - private String username; - - @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Password of the external firewall appliance.") - private String password; - - /////////////////////////////////////////////////// - /////////////////// Accessors /////////////////////// - ///////////////////////////////////////////////////// - - public Long getZoneId() { - return zoneId; - } + @Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the external firewall appliance.") + private String url; + + @Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Username of the external firewall appliance.") + private String username; + + @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Password of the external firewall 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; - } - + public String getUrl() { + return url; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// - @Override - public String getCommandName() { - return s_name; - } - - @Override + @PlugService JuniperSRXFirewallElementService _srxElementService; + + @Override + public String getCommandName() { + return s_name; + } + + @Override public long getEntityOwnerId() { return Account.ACCOUNT_ID_SYSTEM; } - - @Override + + @SuppressWarnings("deprecation") + @Override public void execute(){ - try { - ComponentLocator locator = ComponentLocator.getLocator(ManagementService.Name); - ExternalNetworkDeviceManager externalNetworkMgr = locator.getManager(ExternalNetworkDeviceManager.class); - Host externalFirewall = externalNetworkMgr.addExternalFirewall(this); - ExternalFirewallResponse response = externalNetworkMgr.createExternalFirewallResponse(externalFirewall); - response.setObjectName("externalfirewall"); - 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()); - } + try { + Host externalFirewall = _srxElementService.addExternalFirewall(this); + ExternalFirewallResponse response = _srxElementService.createExternalFirewallResponse(externalFirewall); + response.setObjectName("externalfirewall"); + 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()); + } } } diff --git a/server/src/com/cloud/api/commands/AddExternalLoadBalancerCmd.java b/server/src/com/cloud/api/commands/AddExternalLoadBalancerCmd.java index 7f773a9c3a9..7fce9f8d5dc 100644 --- a/server/src/com/cloud/api/commands/AddExternalLoadBalancerCmd.java +++ b/server/src/com/cloud/api/commands/AddExternalLoadBalancerCmd.java @@ -26,22 +26,22 @@ 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.ExternalNetworkDeviceManager; -import com.cloud.server.ManagementService; +import com.cloud.network.element.F5ExternalLoadBalancerElementService; import com.cloud.server.api.response.ExternalLoadBalancerResponse; import com.cloud.user.Account; -import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.exception.CloudRuntimeException; -@Implementation(description="Adds an external load balancer appliance.", responseObject = ExternalLoadBalancerResponse.class) +@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"; - - ///////////////////////////////////////////////////// + public static final Logger s_logger = Logger.getLogger(AddExternalLoadBalancerCmd.class.getName()); + private static final String s_name = "addexternalloadbalancerresponse"; + + ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// @@ -49,65 +49,64 @@ public class AddExternalLoadBalancerCmd extends BaseCmd { @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; + @Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the external load balancer appliance.") + private String url; - /////////////////////////////////////////////////// - /////////////////// Accessors /////////////////////// - ///////////////////////////////////////////////////// - - public Long getZoneId() { - return zoneId; - } - - public String getUrl() { - return url; - } - - public String getUsername() { - return username; - } - - public String getPassword() { - return password; - } - - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// + @Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Username of the external load balancer appliance.") + private String username; - @Override - public String getCommandName() { - return s_name; - } - - @Override + @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 + + @Override public void execute(){ - try { - ComponentLocator locator = ComponentLocator.getLocator(ManagementService.Name); - ExternalNetworkDeviceManager externalNetworkMgr = locator.getManager(ExternalNetworkDeviceManager.class); - Host externalLoadBalancer = externalNetworkMgr.addExternalLoadBalancer(this); - ExternalLoadBalancerResponse response = externalNetworkMgr.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()); - } + 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 diff --git a/server/src/com/cloud/api/commands/AddNetscalerLoadBalancerCmd.java b/server/src/com/cloud/api/commands/AddNetscalerLoadBalancerCmd.java new file mode 100644 index 00000000000..f76e145cec7 --- /dev/null +++ b/server/src/com/cloud/api/commands/AddNetscalerLoadBalancerCmd.java @@ -0,0 +1,135 @@ +/** + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.api.commands; + +import org.apache.log4j.Logger; +import com.cloud.api.ApiConstants; +import com.cloud.api.BaseAsyncCmd; +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.api.response.NetscalerLoadBalancerResponse; +import com.cloud.event.EventTypes; +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.NetscalerLoadBalancerElementService; +import com.cloud.user.UserContext; +import com.cloud.utils.exception.CloudRuntimeException; + +@Implementation(responseObject=NetscalerLoadBalancerResponse.class, description="Adds a netscaler load balancer device") +public class AddNetscalerLoadBalancerCmd extends BaseAsyncCmd { + + public static final Logger s_logger = Logger.getLogger(AddNetscalerLoadBalancerCmd.class.getName()); + private static final String s_name = "addnetscalerloadbalancerresponse"; + @PlugService NetscalerLoadBalancerElementService _netsclarLbService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @IdentityMapper(entityTableName="physical_network") + @Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.LONG, required=true, description="the Physical Network ID") + private Long physicalNetworkId; + + @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="Credentials to reach netscaler load balancer device") + private String username; + + @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Credentials to reach netscaler load balancer device") + private String password; + + @Parameter(name = ApiConstants.NETWORK_DEVICE_TYPE, type = CommandType.STRING, required = true, description = "Network device type, now supports ExternalDhcp, PxeServer, NetscalerMPXLoadBalancer, NetscalerVPXLoadBalancer, NetscalerSDXLoadBalancer, F5BigIpLoadBalancer, JuniperSRXFirewall") + private String deviceType; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getPhysicalNetworkId() { + return physicalNetworkId; + } + + public String getUrl() { + return url; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public String getDeviceType() { + return deviceType; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + try { + ExternalLoadBalancerDeviceVO lbDeviceVO = _netsclarLbService.addNetscalerLoadBalancer(this); + if (lbDeviceVO != null) { + NetscalerLoadBalancerResponse response = _netsclarLbService.createNetscalerLoadBalancerResponse(lbDeviceVO); + response.setObjectName("netscalerloadbalancer"); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(BaseAsyncCmd.INTERNAL_ERROR, "Failed to add netscaler load balancer due to internal error."); + } + } 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 getEventDescription() { + return "Adding a netscaler load balancer device"; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_EXTERAL_LB_DEVICE_ADD; + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return UserContext.current().getCaller().getId(); + } +} diff --git a/server/src/com/cloud/api/commands/ConfigureNetscalerLoadBalancerCmd.java b/server/src/com/cloud/api/commands/ConfigureNetscalerLoadBalancerCmd.java new file mode 100644 index 00000000000..492562df6ba --- /dev/null +++ b/server/src/com/cloud/api/commands/ConfigureNetscalerLoadBalancerCmd.java @@ -0,0 +1,122 @@ +/** + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.api.commands; + +import org.apache.log4j.Logger; + +import com.cloud.api.ApiConstants; +import com.cloud.api.BaseAsyncCmd; +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.api.response.NetscalerLoadBalancerResponse; +import com.cloud.event.EventTypes; +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.NetscalerLoadBalancerElementService; +import com.cloud.user.UserContext; +import com.cloud.utils.exception.CloudRuntimeException; + +@Implementation(responseObject=NetscalerLoadBalancerResponse.class, description="configures a netscaler load balancer device") +public class ConfigureNetscalerLoadBalancerCmd extends BaseAsyncCmd { + + public static final Logger s_logger = Logger.getLogger(ConfigureNetscalerLoadBalancerCmd.class.getName()); + private static final String s_name = "configurenetscalerloadbalancerresponse"; + @PlugService NetscalerLoadBalancerElementService _netsclarLbService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @IdentityMapper(entityTableName="external_load_balancer_devices") + @Parameter(name=ApiConstants.LOAD_BALANCER_DEVICE_ID, type=CommandType.LONG, required=true, description="the Physical Network ID") + private Long lbDeviceId; + + @Parameter(name=ApiConstants.LOAD_BALANCER_DEVICE_CAPACITY, type=CommandType.LONG, required=false, description="capacity of the device, Capacity will be interpreted as number of networks device can handle") + private Long capacity; + + @Parameter(name=ApiConstants.LOAD_BALANCER_DEVICE_DEDICATED, type=CommandType.BOOLEAN, required=false, description="true if this netscaler device to dedicated for a account") + private Boolean dedicatedUse; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getLoadBalancerDeviceId() { + return lbDeviceId; + } + + public Long getLoadBalancerCapacity() { + return capacity; + } + + public Boolean getLoadBalancerDedicated() { + return dedicatedUse; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + try { + ExternalLoadBalancerDeviceVO lbDeviceVO = _netsclarLbService.configureNetscalerLoadBalancer(this); + if (lbDeviceVO != null) { + NetscalerLoadBalancerResponse response = _netsclarLbService.createNetscalerLoadBalancerResponse(lbDeviceVO); + response.setObjectName("netscalerloadbalancer"); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(BaseAsyncCmd.INTERNAL_ERROR, "Failed to configure netscaler load balancer due to internal error."); + } + } 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 getEventDescription() { + return "Configuring a netscaler load balancer device"; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_EXTERAL_LB_DEVICE_CONFIGURE; + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return UserContext.current().getCaller().getId(); + } +} diff --git a/server/src/com/cloud/api/commands/DeleteExternalFirewallCmd.java b/server/src/com/cloud/api/commands/DeleteExternalFirewallCmd.java index 75e181b9ea8..17fd9bf2235 100644 --- a/server/src/com/cloud/api/commands/DeleteExternalFirewallCmd.java +++ b/server/src/com/cloud/api/commands/DeleteExternalFirewallCmd.java @@ -26,64 +26,64 @@ 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.api.response.SuccessResponse; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.network.ExternalNetworkDeviceManager; -import com.cloud.server.ManagementService; +import com.cloud.network.element.JuniperSRXFirewallElementService; import com.cloud.user.Account; -import com.cloud.utils.component.ComponentLocator; @Implementation(description="Deletes an external firewall appliance.", responseObject = SuccessResponse.class) public class DeleteExternalFirewallCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteExternalFirewallCmd.class.getName()); - private static final String s_name = "deleteexternalfirewallresponse"; - - ///////////////////////////////////////////////////// + public static final Logger s_logger = Logger.getLogger(DeleteExternalFirewallCmd.class.getName()); + private static final String s_name = "deleteexternalfirewallresponse"; + + ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - - @IdentityMapper(entityTableName="host") - @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required = true, description="Id of the external firewall appliance.") - private Long id; - - /////////////////////////////////////////////////// - /////////////////// Accessors /////////////////////// - ///////////////////////////////////////////////////// - - public Long getId() { - return id; - } - - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// - @Override - public String getCommandName() { - return s_name; - } - - @Override + @IdentityMapper(entityTableName="host") + @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required = true, description="Id of the external firewall appliance.") + private Long id; + + /////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @PlugService JuniperSRXFirewallElementService _srxElementService; + + @Override + public String getCommandName() { + return s_name; + } + + @Override public long getEntityOwnerId() { return Account.ACCOUNT_ID_SYSTEM; } - - @Override + + @SuppressWarnings("deprecation") + @Override public void execute(){ - try { - ComponentLocator locator = ComponentLocator.getLocator(ManagementService.Name); - ExternalNetworkDeviceManager externalNetworkMgr = locator.getManager(ExternalNetworkDeviceManager.class); - boolean result = externalNetworkMgr.deleteExternalFirewall(this); - if (result) { - SuccessResponse response = new SuccessResponse(getCommandName()); - response.setResponseName(getCommandName()); - this.setResponseObject(response); - } else { - throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete external firewall."); - } - } catch (InvalidParameterValueException e) { - throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to delete external firewall."); - } + try { + boolean result = _srxElementService.deleteExternalFirewall(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete external firewall."); + } + } catch (InvalidParameterValueException e) { + throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to delete external firewall."); + } } } diff --git a/server/src/com/cloud/api/commands/DeleteExternalLoadBalancerCmd.java b/server/src/com/cloud/api/commands/DeleteExternalLoadBalancerCmd.java index 735523330e0..6e67e9d9895 100644 --- a/server/src/com/cloud/api/commands/DeleteExternalLoadBalancerCmd.java +++ b/server/src/com/cloud/api/commands/DeleteExternalLoadBalancerCmd.java @@ -26,64 +26,65 @@ 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.api.response.SuccessResponse; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.network.ExternalNetworkDeviceManager; -import com.cloud.server.ManagementService; +import com.cloud.network.element.F5ExternalLoadBalancerElementService; import com.cloud.user.Account; -import com.cloud.utils.component.ComponentLocator; -@Implementation(description="Deletes an external load balancer appliance.", responseObject = SuccessResponse.class) +@Implementation(description="Deletes a F5 external load balancer appliance added in a zone.", responseObject = SuccessResponse.class) +@Deprecated // API supported for backward compatibility. public class DeleteExternalLoadBalancerCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteExternalLoadBalancerCmd.class.getName()); - private static final String s_name = "deleteexternalloadbalancerresponse"; - - ///////////////////////////////////////////////////// + public static final Logger s_logger = Logger.getLogger(DeleteExternalLoadBalancerCmd.class.getName()); + private static final String s_name = "deleteexternalloadbalancerresponse"; + + ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - + @IdentityMapper(entityTableName="host") - @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required = true, description="Id of the external loadbalancer appliance.") - private Long id; - - /////////////////////////////////////////////////// - /////////////////// Accessors /////////////////////// - ///////////////////////////////////////////////////// - - public Long getId() { - return id; - } - - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// + @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required = true, description="Id of the external loadbalancer appliance.") + private Long id; + + /////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } - @Override - public String getCommandName() { - return s_name; - } - - @Override + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @PlugService + F5ExternalLoadBalancerElementService _f5DeviceManagerService; + + @Override + public String getCommandName() { + return s_name; + } + + @Override public long getEntityOwnerId() { return Account.ACCOUNT_ID_SYSTEM; } - - @Override + + @Override public void execute(){ - try { - ComponentLocator locator = ComponentLocator.getLocator(ManagementService.Name); - ExternalNetworkDeviceManager externalNetworkMgr = locator.getManager(ExternalNetworkDeviceManager.class); - boolean result = externalNetworkMgr.deleteExternalLoadBalancer(this); - if (result) { - SuccessResponse response = new SuccessResponse(getCommandName()); - response.setResponseName(getCommandName()); - this.setResponseObject(response); - } else { - throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete external load balancer."); - } - } catch (InvalidParameterValueException e) { - throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to delete external load balancer."); - } + try { + boolean result = _f5DeviceManagerService.deleteExternalLoadBalancer(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete external load balancer."); + } + } catch (InvalidParameterValueException e) { + throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to delete external load balancer."); + } } } diff --git a/server/src/com/cloud/api/commands/DeleteNetscalerLoadBalancerCmd.java b/server/src/com/cloud/api/commands/DeleteNetscalerLoadBalancerCmd.java new file mode 100644 index 00000000000..7f73831c9b7 --- /dev/null +++ b/server/src/com/cloud/api/commands/DeleteNetscalerLoadBalancerCmd.java @@ -0,0 +1,106 @@ +/** + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.api.commands; + +import org.apache.log4j.Logger; + +import com.cloud.api.ApiConstants; +import com.cloud.api.BaseAsyncCmd; +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.api.response.SuccessResponse; +import com.cloud.event.EventTypes; +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.element.NetscalerLoadBalancerElementService; +import com.cloud.user.UserContext; +import com.cloud.utils.exception.CloudRuntimeException; + +@Implementation(responseObject=SuccessResponse.class, description=" delete a netscaler load balancer device") +public class DeleteNetscalerLoadBalancerCmd extends BaseAsyncCmd { + + public static final Logger s_logger = Logger.getLogger(DeleteNetscalerLoadBalancerCmd.class.getName()); + private static final String s_name = "deletenetscalerloadbalancerresponse"; + @PlugService NetscalerLoadBalancerElementService _netsclarLbService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @IdentityMapper(entityTableName="external_load_balancer_devices") + @Parameter(name=ApiConstants.LOAD_BALANCER_DEVICE_ID, type=CommandType.LONG, required=true, description="netscaler 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 { + boolean result = _netsclarLbService.deleteNetscalerLoadBalancer(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete netscaler load balancer."); + } + } 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 getEventDescription() { + return "Deleting a netscaler load balancer device"; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_LOAD_BALANCER_DELETE; + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return UserContext.current().getCaller().getId(); + } +} diff --git a/server/src/com/cloud/api/commands/ListExternalFirewallsCmd.java b/server/src/com/cloud/api/commands/ListExternalFirewallsCmd.java index a2c30e5536f..75269692092 100644 --- a/server/src/com/cloud/api/commands/ListExternalFirewallsCmd.java +++ b/server/src/com/cloud/api/commands/ListExternalFirewallsCmd.java @@ -29,13 +29,11 @@ import com.cloud.api.BaseListCmd; import com.cloud.api.IdentityMapper; import com.cloud.api.Implementation; import com.cloud.api.Parameter; -import com.cloud.api.BaseCmd.CommandType; +import com.cloud.api.PlugService; import com.cloud.api.response.ListResponse; import com.cloud.host.Host; -import com.cloud.network.ExternalNetworkDeviceManager; -import com.cloud.server.ManagementService; +import com.cloud.network.element.JuniperSRXFirewallElementService; import com.cloud.server.api.response.ExternalFirewallResponse; -import com.cloud.utils.component.ComponentLocator; @Implementation(description="List external firewall appliances.", responseObject = ExternalFirewallResponse.class) public class ListExternalFirewallsCmd extends BaseListCmd { @@ -62,21 +60,23 @@ public class ListExternalFirewallsCmd extends BaseListCmd { /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// + @PlugService JuniperSRXFirewallElementService _srxElementService; + @Override public String getCommandName() { return s_name; } + @SuppressWarnings("deprecation") @Override public void execute(){ - ComponentLocator locator = ComponentLocator.getLocator(ManagementService.Name); - ExternalNetworkDeviceManager externalNetworkMgr = locator.getManager(ExternalNetworkDeviceManager.class); - List externalFirewalls = externalNetworkMgr.listExternalFirewalls(this); + + List externalFirewalls = _srxElementService.listExternalFirewalls(this); ListResponse listResponse = new ListResponse(); List responses = new ArrayList(); for (Host externalFirewall : externalFirewalls) { - ExternalFirewallResponse response = externalNetworkMgr.createExternalFirewallResponse(externalFirewall); + ExternalFirewallResponse response = _srxElementService.createExternalFirewallResponse(externalFirewall); response.setObjectName("externalfirewall"); response.setResponseName(getCommandName()); responses.add(response); diff --git a/server/src/com/cloud/api/commands/ListExternalLoadBalancersCmd.java b/server/src/com/cloud/api/commands/ListExternalLoadBalancersCmd.java index f26d507dbad..9b2aeb22805 100644 --- a/server/src/com/cloud/api/commands/ListExternalLoadBalancersCmd.java +++ b/server/src/com/cloud/api/commands/ListExternalLoadBalancersCmd.java @@ -29,16 +29,15 @@ import com.cloud.api.BaseListCmd; import com.cloud.api.IdentityMapper; import com.cloud.api.Implementation; import com.cloud.api.Parameter; -import com.cloud.api.BaseCmd.CommandType; +import com.cloud.api.PlugService; import com.cloud.api.response.HostResponse; import com.cloud.api.response.ListResponse; import com.cloud.host.Host; -import com.cloud.network.ExternalNetworkDeviceManager; -import com.cloud.server.ManagementService; +import com.cloud.network.element.F5ExternalLoadBalancerElementService; import com.cloud.server.api.response.ExternalLoadBalancerResponse; -import com.cloud.utils.component.ComponentLocator; -@Implementation(description="List external load balancer appliances.", responseObject = HostResponse.class) +@Implementation(description="Lists F5 external load balancer appliances added in a zone.", responseObject = HostResponse.class) +@Deprecated // API supported for backward compatibility. public class ListExternalLoadBalancersCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListExternalLoadBalancersCmd.class.getName()); private static final String s_name = "listexternalloadbalancersresponse"; @@ -63,6 +62,9 @@ public class ListExternalLoadBalancersCmd extends BaseListCmd { /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// + @PlugService + F5ExternalLoadBalancerElementService _f5DeviceManagerService; + @Override public String getCommandName() { return s_name; @@ -70,14 +72,11 @@ public class ListExternalLoadBalancersCmd extends BaseListCmd { @Override public void execute(){ - ComponentLocator locator = ComponentLocator.getLocator(ManagementService.Name); - ExternalNetworkDeviceManager externalNetworkMgr = locator.getManager(ExternalNetworkDeviceManager.class); - List externalLoadBalancers = externalNetworkMgr.listExternalLoadBalancers(this); - + List externalLoadBalancers = _f5DeviceManagerService.listExternalLoadBalancers(this); ListResponse listResponse = new ListResponse(); List responses = new ArrayList(); for (Host externalLoadBalancer : externalLoadBalancers) { - ExternalLoadBalancerResponse response = externalNetworkMgr.createExternalLoadBalancerResponse(externalLoadBalancer); + ExternalLoadBalancerResponse response = _f5DeviceManagerService.createExternalLoadBalancerResponse(externalLoadBalancer); response.setObjectName("externalloadbalancer"); response.setResponseName(getCommandName()); responses.add(response); diff --git a/server/src/com/cloud/api/commands/ListNetscalerLoadBalancerNetworksCmd.java b/server/src/com/cloud/api/commands/ListNetscalerLoadBalancerNetworksCmd.java new file mode 100644 index 00000000000..d794ba6f159 --- /dev/null +++ b/server/src/com/cloud/api/commands/ListNetscalerLoadBalancerNetworksCmd.java @@ -0,0 +1,82 @@ +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.NetscalerLoadBalancerElementService; +import com.cloud.utils.exception.CloudRuntimeException; + +@Implementation(responseObject=NetworkResponse.class, description="lists network that are using a netscaler load balancer device") +public class ListNetscalerLoadBalancerNetworksCmd extends BaseListCmd { + + public static final Logger s_logger = Logger.getLogger(ListNetscalerLoadBalancerNetworksCmd.class.getName()); + private static final String s_name = "listnetscalerloadbalancernetworksresponse"; + @PlugService NetscalerLoadBalancerElementService _netsclarLbService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @IdentityMapper(entityTableName="external_load_balancer_devices") + @Parameter(name=ApiConstants.LOAD_BALANCER_DEVICE_ID, type=CommandType.LONG, required = true, description="netscaler 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 networks = _netsclarLbService.listNetworks(this); + ListResponse response = new ListResponse(); + List networkResponses = new ArrayList(); + + 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; + } +} diff --git a/server/src/com/cloud/api/commands/ListNetscalerLoadBalancersCmd.java b/server/src/com/cloud/api/commands/ListNetscalerLoadBalancersCmd.java new file mode 100644 index 00000000000..48673168f78 --- /dev/null +++ b/server/src/com/cloud/api/commands/ListNetscalerLoadBalancersCmd.java @@ -0,0 +1,108 @@ +/** + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +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.NetscalerLoadBalancerResponse; +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.NetscalerLoadBalancerElementService; +import com.cloud.utils.exception.CloudRuntimeException; + +@Implementation(responseObject=NetscalerLoadBalancerResponse.class, description="lists netscaler load balancer devices") +public class ListNetscalerLoadBalancersCmd extends BaseListCmd { + + public static final Logger s_logger = Logger.getLogger(ListNetscalerLoadBalancersCmd.class.getName()); + private static final String s_name = "listnetscalerloadbalancerresponse"; + @PlugService NetscalerLoadBalancerElementService _netsclarLbService; + + ///////////////////////////////////////////////////// + //////////////// 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="netscaler 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 lbDevices = _netsclarLbService.listNetscalerLoadBalancers(this); + ListResponse response = new ListResponse(); + List lbDevicesResponse = new ArrayList(); + + if (lbDevices != null && !lbDevices.isEmpty()) { + for (ExternalLoadBalancerDeviceVO lbDeviceVO : lbDevices) { + NetscalerLoadBalancerResponse lbdeviceResponse = _netsclarLbService.createNetscalerLoadBalancerResponse(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; + } +} diff --git a/server/src/com/cloud/configuration/DefaultComponentLibrary.java b/server/src/com/cloud/configuration/DefaultComponentLibrary.java index c2c56224578..a3bb83d72ba 100755 --- a/server/src/com/cloud/configuration/DefaultComponentLibrary.java +++ b/server/src/com/cloud/configuration/DefaultComponentLibrary.java @@ -92,6 +92,12 @@ import com.cloud.network.dao.PhysicalNetworkTrafficTypeDaoImpl; import com.cloud.network.dao.RemoteAccessVpnDaoImpl; import com.cloud.network.dao.VirtualRouterProviderDaoImpl; import com.cloud.network.dao.VpnUserDaoImpl; +import com.cloud.network.element.F5ExternalLoadBalancerElement; +import com.cloud.network.element.F5ExternalLoadBalancerElementService; +import com.cloud.network.element.JuniperSRXExternalFirewallElement; +import com.cloud.network.element.JuniperSRXFirewallElementService; +import com.cloud.network.element.NetscalerExternalLoadBalancerElement; +import com.cloud.network.element.NetscalerLoadBalancerElementService; import com.cloud.network.element.VirtualRouterElement; import com.cloud.network.element.VirtualRouterElementService; import com.cloud.network.firewall.FirewallManagerImpl; @@ -399,6 +405,9 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com protected void populateServices() { addService("VirtualRouterElementService", VirtualRouterElementService.class, VirtualRouterElement.class); + addService("NetscalerExternalLoadBalancerElementService", NetscalerLoadBalancerElementService.class, NetscalerExternalLoadBalancerElement.class); + addService("F5LoadBalancerElementService", F5ExternalLoadBalancerElementService.class, F5ExternalLoadBalancerElement.class); + addService("JuniperSRXFirewallElementService", JuniperSRXFirewallElementService.class, JuniperSRXExternalFirewallElement.class); } @Override diff --git a/server/src/com/cloud/network/ExternalFirewallDeviceManager.java b/server/src/com/cloud/network/ExternalFirewallDeviceManager.java new file mode 100644 index 00000000000..9f0582ba5a0 --- /dev/null +++ b/server/src/com/cloud/network/ExternalFirewallDeviceManager.java @@ -0,0 +1,100 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.network; + +import java.util.List; + +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.host.Host; +import com.cloud.network.rules.FirewallRule; +import com.cloud.resource.ServerResource; +import com.cloud.utils.component.Manager; + +/* ExternalFirewallDeviceManager provides a abstract implementation for managing a external firewall in devices agnostic manner. + * Device specific managers for external firewall (like SRX) should be implemented as pluggable service extending + * ExternalFirewallDeviceManager implementation. An implementation of device specific manager can override default behaviour when needed. + */ + +public interface ExternalFirewallDeviceManager extends Manager { + + /** + * adds a firewall device in to a physical network + * @param physicalNetworkId physical network id of the network in to which device to be added + * @param url url encoding device IP and device configuration parameter + * @param username username + * @param password password + * @param deviceName device name + * @param server resource that will handle the commands specific to this device + * @return Host object for the device added + */ + public Host addExternalFirewall(long physicalNetworkId, String url, String username, String password, String deviceName, ServerResource resource); + + /** + * deletes load balancer device added in to a physical network + * @param hostId + * @return true if device successfully deleted + */ + public boolean deleteExternalFirewall(Long hostId); + + /** + * list external firewall devices of given device name type added in to a physical network + * @param physicalNetworkId + * @param deviceName + * @return list of host objects for the external load balancers added in to the physical network + */ + public List listExternalFirewalls(long physicalNetworkId, String deviceName); + + /** + * finds a suitable firewall device which can be used by this network + * @param network guest network + * @param dedicatedLb true if a dedicated load balancer is needed for this guest network + * @return ExternalLoadBalancerDeviceVO corresponding to the suitable device + * @throws InsufficientCapacityException + */ + public ExternalFirewallDeviceVO findSuitableFirewallForNetwork(Network network) throws InsufficientCapacityException; + + /** + * returns the firewall device allocated for the guest network + * @param network guest network id + * @return ExternalFirewallDeviceVO object corresponding the firewall device assigned for this guest network + */ + public ExternalFirewallDeviceVO getExternalFirewallForNetwork(Network network); + + /** + * applies firewall rules + * @param network guest network if + * @param rules load balancer rules + * @return true if successfully applied rules + * @throws ResourceUnavailableException + */ + public boolean applyFirewallRules(Network network, List rules) throws ResourceUnavailableException; + + /** + * implements or shutdowns guest network on the firewall device assigned to the guest network + * @param add + * @param guestConfig + * @return + * @throws ResourceUnavailableException + * @throws InsufficientCapacityException + */ + public boolean manageGuestNetworkWithExternalFirewall(boolean add, Network guestConfig) throws ResourceUnavailableException, InsufficientCapacityException; + +} diff --git a/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java new file mode 100644 index 00000000000..f66b51312d9 --- /dev/null +++ b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java @@ -0,0 +1,613 @@ +package com.cloud.network; + +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupExternalLoadBalancerCommand; +import com.cloud.agent.api.routing.IpAssocCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; +import com.cloud.agent.api.routing.VpnUsersCfgCommand; +import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.agent.api.to.PortForwardingRuleTO; +import com.cloud.agent.api.to.StaticNatRuleTO; +import com.cloud.api.ApiConstants; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.Vlan; +import com.cloud.dc.VlanVO; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.VlanDao; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InsufficientNetworkCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.host.DetailVO; +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.ExternalNetworkDeviceManager.NetworkDevice; +import com.cloud.network.Network.Capability; +import com.cloud.network.Network.Service; +import com.cloud.network.Networks.TrafficType; +import com.cloud.network.dao.ExternalFirewallDeviceDao; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.network.dao.InlineLoadBalancerNicMapDao; +import com.cloud.network.dao.LoadBalancerDao; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkExternalFirewallDao; +import com.cloud.network.dao.NetworkServiceMapDao; +import com.cloud.network.dao.PhysicalNetworkDao; +import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; +import com.cloud.network.dao.PhysicalNetworkServiceProviderVO; +import com.cloud.network.dao.VpnUserDao; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.StaticNatRule; +import com.cloud.network.rules.FirewallRule.Purpose; +import com.cloud.network.rules.dao.PortForwardingRulesDao; +import com.cloud.offerings.dao.NetworkOfferingDao; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceStateAdapter; +import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; +import com.cloud.resource.ResourceStateAdapter.DeleteHostAnswer; +import com.cloud.server.api.response.ExternalFirewallResponse; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.dao.AccountDao; +import com.cloud.user.dao.UserStatisticsDao; +import com.cloud.utils.component.AdapterBase; +import com.cloud.utils.component.Inject; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.GlobalLock; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.NetUtils; +import com.cloud.utils.net.UrlUtil; +import com.cloud.vm.NicVO; +import com.cloud.vm.Nic.ReservationStrategy; +import com.cloud.vm.Nic.State; +import com.cloud.vm.dao.DomainRouterDao; +import com.cloud.vm.dao.NicDao; + +public abstract class ExternalFirewallDeviceManagerImpl extends AdapterBase implements ExternalFirewallDeviceManager, ResourceStateAdapter { + + @Inject HostDao _hostDao; + @Inject NetworkServiceMapDao _ntwkSrvcProviderDao; + @Inject DataCenterDao _dcDao; + @Inject HostDetailsDao _detailsDao; + @Inject NetworkManager _networkMgr; + @Inject InlineLoadBalancerNicMapDao _inlineLoadBalancerNicMapDao; + @Inject NicDao _nicDao; + @Inject AgentManager _agentMgr; + @Inject ResourceManager _resourceMgr; + @Inject IPAddressDao _ipAddressDao; + @Inject VlanDao _vlanDao; + @Inject NetworkOfferingDao _networkOfferingDao; + @Inject AccountDao _accountDao; + @Inject PhysicalNetworkDao _physicalNetworkDao; + @Inject PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao; + @Inject AccountManager _accountMgr; + @Inject UserStatisticsDao _userStatsDao; + @Inject NetworkDao _networkDao; + @Inject DomainRouterDao _routerDao; + @Inject LoadBalancerDao _loadBalancerDao; + @Inject PortForwardingRulesDao _portForwardingRulesDao; + @Inject ConfigurationDao _configDao; + @Inject ExternalFirewallDeviceDao _externalFirewallDeviceDao; + @Inject NetworkExternalFirewallDao _networkExternalFirewallDao; + @Inject VpnUserDao _vpnUsersDao; + @Inject HostDetailsDao _hostDetailDao; + + private static final org.apache.log4j.Logger s_logger = Logger.getLogger(ExternalFirewallDeviceManagerImpl.class); + + @Override + @DB + public Host addExternalFirewall(long physicalNetworkId, String url, String username, String password, String deviceName, ServerResource resource) { + String guid; + PhysicalNetworkVO pNetwork=null; + NetworkDevice ntwkDevice = NetworkDevice.getNetworkDevice(deviceName); + long zoneId; + + if ((ntwkDevice == null) || (url == null) || (username == null) || (resource == null) || (password == null) ) { + throw new InvalidParameterValueException("Atleast one of the required parameters (url, username, password," + + " server resource, zone id/physical network id) is not specified or a valid parameter."); + } + + pNetwork = _physicalNetworkDao.findById(physicalNetworkId); + if (pNetwork == null) { + throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId); + } + zoneId = pNetwork.getDataCenterId(); + + PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), ntwkDevice.getNetworkServiceProvder()); + if (ntwkSvcProvider == null ) { + throw new CloudRuntimeException("Network Service Provider: " + ntwkDevice.getNetworkServiceProvder() + + " is not enabled in the physical network: " + physicalNetworkId + "to add this device" ); + } else if ((ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) + || (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Disabled)) { + throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() + + " is not added or in shutdown state in the physical network: " + physicalNetworkId + "to add this device" ); + } + + URI uri; + try { + uri = new URI(url); + } catch (Exception e) { + s_logger.debug(e); + throw new InvalidParameterValueException(e.getMessage()); + } + + String ipAddress = uri.getHost(); + Map hostDetails = new HashMap(); + guid = getExternalNetworkResourceGuid(pNetwork.getId(), deviceName, ipAddress); + hostDetails.put("guid", guid); + hostDetails.put("zoneId", String.valueOf(pNetwork.getDataCenterId())); + hostDetails.put("ip", ipAddress); + hostDetails.put("physicalNetworkId", String.valueOf(pNetwork.getId())); + hostDetails.put("username", username); + hostDetails.put("password", password); + hostDetails.put("deviceName", deviceName); + Map params = new HashMap(); + UrlUtil.parseQueryParameters(uri.getQuery(), false, params); + hostDetails.putAll(params); + + // let the server resource to device parameters validation + try { + resource.configure(guid, hostDetails); + } catch (ConfigurationException e) { + throw new CloudRuntimeException(e.getMessage()); + } + + Host externalFirewall = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalFirewall, hostDetails); + if (externalFirewall != null) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + + ExternalFirewallDeviceVO fwDevice = new ExternalFirewallDeviceVO(externalFirewall.getId(), pNetwork.getId(), ntwkSvcProvider.getProviderName(), deviceName); + _externalFirewallDeviceDao.persist(fwDevice); + + DetailVO hostDetail = new DetailVO(externalFirewall.getId(), ApiConstants.FIREWALL_DEVICE_ID, String.valueOf(fwDevice.getId())); + _hostDetailDao.persist(hostDetail); + + txn.commit(); + return externalFirewall; + } else { + return null; + } + } + + @Override + public boolean deleteExternalFirewall(Long hostId) { + HostVO externalFirewall = _hostDao.findById(hostId); + if (externalFirewall == null) { + throw new InvalidParameterValueException("Could not find an external firewall with ID: " + hostId); + } + + try { + if (_resourceMgr.maintain(hostId) && _resourceMgr.deleteHost(hostId, false, false)) { + return true; + } else { + return false; + } + } catch (AgentUnavailableException e) { + s_logger.debug(e); + return false; + } + } + + @Override + public List listExternalFirewalls(long physicalNetworkId, String deviceName) { + List firewallHosts = new ArrayList(); + NetworkDevice fwNetworkDevice = NetworkDevice.getNetworkDevice(deviceName); + PhysicalNetworkVO pNetwork=null; + + pNetwork = _physicalNetworkDao.findById(physicalNetworkId); + if (pNetwork == null) { + throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId); + } + + if ((pNetwork == null) || (fwNetworkDevice == null)) { + throw new InvalidParameterValueException("Atleast one of ther required parameter physical networkId, device name is missing or invalid."); + } + + PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), fwNetworkDevice.getNetworkServiceProvder()); + if (ntwkSvcProvider == null) { + return null; + } + + List fwDevices = _externalFirewallDeviceDao.listByPhysicalNetworkAndProvider(physicalNetworkId, ntwkSvcProvider.getProviderName()); + for (ExternalFirewallDeviceVO fwDevice : fwDevices) { + firewallHosts.add(_hostDao.findById(fwDevice.getHostId())); + } + return firewallHosts; + } + + public ExternalFirewallDeviceVO getExternalFirewallForNetwork(Network network) { + NetworkExternalFirewallVO fwDeviceForNetwork = _networkExternalFirewallDao.findByNetworkId(network.getId()); + if (fwDeviceForNetwork != null) { + long fwDeviceId = fwDeviceForNetwork.getExternalFirewallDeviceId(); + ExternalFirewallDeviceVO fwDevice = _externalFirewallDeviceDao.findById(fwDeviceId); + assert(fwDevice != null); + return fwDevice; + } + return null; + } + + public void setExternalFirewallForNetwork(Network network, long externalFWDeviceID) { + NetworkExternalFirewallVO fwDeviceForNetwork = new NetworkExternalFirewallVO(network.getId(), externalFWDeviceID); + _networkExternalFirewallDao.persist(fwDeviceForNetwork); + } + + @Override + public ExternalFirewallDeviceVO findSuitableFirewallForNetwork(Network network) throws InsufficientCapacityException { + long physicalNetworkId = network.getPhysicalNetworkId(); + List fwDevices = _externalFirewallDeviceDao.listByPhysicalNetwork(physicalNetworkId); + + // loop through the firewall device in the physical network and pick the first-fit + for (ExternalFirewallDeviceVO fwDevice: fwDevices) { + // max number of guest networks that can be mapped to this device + long fullCapacity = fwDevice.getCapacity(); + + // get the list of guest networks that are mapped to this load balancer + List mappedNetworks = _networkExternalFirewallDao.listByFirewallDeviceId(fwDevice.getId()); + + long usedCapacity = (mappedNetworks == null) ? 0 : mappedNetworks.size(); + if ((fullCapacity - usedCapacity) > 0) { + return fwDevice; + } + } + throw new InsufficientNetworkCapacityException("Unable to find a firewall provider with sufficient capcity " + + " to implement the network", Network.class, network.getId()); + } + + public String getExternalNetworkResourceGuid(long physicalNetworkId, String deviceName, String ip) { + return physicalNetworkId + "-" + deviceName + "-" + ip; + } + + public ExternalFirewallResponse createExternalFirewallResponse(Host externalFirewall) { + Map fwDetails = _detailsDao.findDetails(externalFirewall.getId()); + ExternalFirewallResponse response = new ExternalFirewallResponse(); + response.setId(externalFirewall.getId()); + response.setIpAddress(externalFirewall.getPrivateIpAddress()); + response.setUsername(fwDetails.get("username")); + response.setPublicInterface(fwDetails.get("publicInterface")); + response.setUsageInterface(fwDetails.get("usageInterface")); + response.setPrivateInterface(fwDetails.get("privateInterface")); + response.setPublicZone(fwDetails.get("publicZone")); + response.setPrivateZone(fwDetails.get("privateZone")); + response.setNumRetries(fwDetails.get("numRetries")); + response.setTimeout(fwDetails.get("timeout")); + return response; + } + + @Override + public boolean manageGuestNetworkWithExternalFirewall(boolean add, Network network) throws ResourceUnavailableException, InsufficientCapacityException { + if (network.getTrafficType() != TrafficType.Guest) { + s_logger.trace("External firewall can only be used for add/remove guest networks."); + return false; + } + + long zoneId = network.getDataCenterId(); + DataCenterVO zone = _dcDao.findById(zoneId); + HostVO externalFirewall = null; + + if (add) { + GlobalLock deviceMapLock = GlobalLock.getInternLock("NetworkFirewallDeviceMap"); + try { + if (deviceMapLock.lock(120)) { + try { + ExternalFirewallDeviceVO device = findSuitableFirewallForNetwork(network); + long externalFirewallId = device.getId(); + + NetworkExternalFirewallVO networkFW = new NetworkExternalFirewallVO(network.getId(), externalFirewallId); + _networkExternalFirewallDao.persist(networkFW); + + externalFirewall = _hostDao.findById(device.getHostId()); + } finally { + deviceMapLock.unlock(); + } + } + } finally { + deviceMapLock.releaseRef(); + } + } else { + ExternalFirewallDeviceVO fwDeviceVO = getExternalFirewallForNetwork(network); + externalFirewall = _hostDao.findById(fwDeviceVO.getHostId()); + } + + Account account = _accountDao.findByIdIncludingRemoved(network.getAccountId()); + + boolean sharedSourceNat = false; + Map sourceNatCapabilities = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.SourceNat); + if (sourceNatCapabilities != null) { + String supportedSourceNatTypes = sourceNatCapabilities.get(Capability.SupportedSourceNatTypes).toLowerCase(); + if (supportedSourceNatTypes.contains("zone")) { + sharedSourceNat = true; + } + } + + IPAddressVO sourceNatIp = null; + if (!sharedSourceNat) { + // Get the source NAT IP address for this network + List sourceNatIps = _networkMgr.listPublicIpAddressesInVirtualNetwork(network.getAccountId(), zoneId, true, null); + + if (sourceNatIps.size() != 1) { + String errorMsg = "External firewall was unable to find the source NAT IP address for account " + account.getAccountName(); + s_logger.error(errorMsg); + return true; + } else { + sourceNatIp = sourceNatIps.get(0); + } + } + + // Send a command to the external firewall to implement or shutdown the guest network + long guestVlanTag = Long.parseLong(network.getBroadcastUri().getHost()); + String guestVlanGateway = network.getGateway(); + String guestVlanCidr = network.getCidr(); + String sourceNatIpAddress = sourceNatIp.getAddress().addr(); + + VlanVO publicVlan = _vlanDao.findById(sourceNatIp.getVlanId()); + String publicVlanTag = publicVlan.getVlanTag(); + + // Get network rate + Integer networkRate = _networkMgr.getNetworkRate(network.getId(), null); + + IpAddressTO ip = new IpAddressTO(account.getAccountId(), sourceNatIpAddress, add, false, !sharedSourceNat, publicVlanTag, null, null, null, null, networkRate, sourceNatIp.isOneToOneNat()); + IpAddressTO[] ips = new IpAddressTO[1]; + ips[0] = ip; + IpAssocCommand cmd = new IpAssocCommand(ips); + cmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_GATEWAY, guestVlanGateway); + cmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR, guestVlanCidr); + cmd.setAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG, String.valueOf(guestVlanTag)); + Answer answer = _agentMgr.easySend(externalFirewall.getId(), cmd); + + if (answer == null || !answer.getResult()) { + String action = add ? "implement" : "shutdown"; + String answerDetails = (answer != null) ? answer.getDetails() : "answer was null"; + String msg = "External firewall was unable to " + action + " the guest network on the external firewall in zone " + zone.getName() + " due to " + answerDetails; + s_logger.error(msg); + throw new ResourceUnavailableException(msg, DataCenter.class, zoneId); + } + + List reservedIpAddressesForGuestNetwork = _nicDao.listIpAddressInNetwork(network.getId()); + if (add && (!reservedIpAddressesForGuestNetwork.contains(network.getGateway()))) { + // Insert a new NIC for this guest network to reserve the gateway address + savePlaceholderNic(network, network.getGateway()); + } + + // Delete any mappings used for inline external load balancers in this network + List nicsInNetwork = _nicDao.listByNetworkId(network.getId()); + for (NicVO nic : nicsInNetwork) { + InlineLoadBalancerNicMapVO mapping = _inlineLoadBalancerNicMapDao.findByNicId(nic.getId()); + + if (mapping != null) { + _nicDao.expunge(mapping.getNicId()); + _inlineLoadBalancerNicMapDao.expunge(mapping.getId()); + + } + } + + + String action = add ? "implemented" : "shut down"; + s_logger.debug("External firewall has " + action + " the guest network for account " + account.getAccountName() + "(id = " + account.getAccountId() + ") with VLAN tag " + guestVlanTag); + + return true; + } + + @Override + public boolean applyFirewallRules(Network network, List rules) throws ResourceUnavailableException { + // Find the external firewall in this zone + long zoneId = network.getDataCenterId(); + DataCenterVO zone = _dcDao.findById(zoneId); + ExternalFirewallDeviceVO fwDeviceVO = getExternalFirewallForNetwork(network); + HostVO externalFirewall = _hostDao.findById(fwDeviceVO.getHostId()); + + assert(externalFirewall != null); + + if (network.getState() == Network.State.Allocated) { + s_logger.debug("External firewall was asked to apply firewall rules for network with ID " + network.getId() + "; this network is not implemented. Skipping backend commands."); + return true; + } + + List staticNatRules = new ArrayList(); + List portForwardingRules = new ArrayList(); + + for (FirewallRule rule : rules) { + IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId()); + Vlan vlan = _vlanDao.findById(sourceIp.getVlanId()); + + if (rule.getPurpose() == Purpose.StaticNat) { + StaticNatRule staticNatRule = (StaticNatRule) rule; + StaticNatRuleTO ruleTO = new StaticNatRuleTO(staticNatRule, vlan.getVlanTag(), sourceIp.getAddress().addr(), staticNatRule.getDestIpAddress()); + staticNatRules.add(ruleTO); + } else if (rule.getPurpose() == Purpose.PortForwarding) { + PortForwardingRuleTO ruleTO = new PortForwardingRuleTO((PortForwardingRule) rule, vlan.getVlanTag(), sourceIp.getAddress().addr()); + portForwardingRules.add(ruleTO); + } + } + + // Apply static nat rules + applyStaticNatRules(staticNatRules, zone, externalFirewall.getId()); + + // apply port forwarding rules + applyPortForwardingRules(portForwardingRules, zone, externalFirewall.getId()); + + return true; + } + + protected void applyStaticNatRules(List staticNatRules, DataCenter zone, long externalFirewallId) throws ResourceUnavailableException { + if (!staticNatRules.isEmpty()) { + SetStaticNatRulesCommand cmd = new SetStaticNatRulesCommand(staticNatRules); + Answer answer = _agentMgr.easySend(externalFirewallId, cmd); + if (answer == null || !answer.getResult()) { + String details = (answer != null) ? answer.getDetails() : "details unavailable"; + String msg = "External firewall was unable to apply static nat rules to the SRX appliance in zone " + zone.getName() + " due to: " + details + "."; + s_logger.error(msg); + throw new ResourceUnavailableException(msg, DataCenter.class, zone.getId()); + } + } + } + + protected void applyPortForwardingRules(List portForwardingRules, DataCenter zone, long externalFirewallId) throws ResourceUnavailableException { + if (!portForwardingRules.isEmpty()) { + SetPortForwardingRulesCommand cmd = new SetPortForwardingRulesCommand(portForwardingRules); + Answer answer = _agentMgr.easySend(externalFirewallId, cmd); + if (answer == null || !answer.getResult()) { + String details = (answer != null) ? answer.getDetails() : "details unavailable"; + String msg = "External firewall was unable to apply port forwarding rules to the SRX appliance in zone " + zone.getName() + " due to: " + details + "."; + s_logger.error(msg); + throw new ResourceUnavailableException(msg, DataCenter.class, zone.getId()); + } + } + } + + public boolean applyIps(Network network, List ipAddresses) throws ResourceUnavailableException { + return true; + } + + public boolean manageRemoteAccessVpn(boolean create, Network network, RemoteAccessVpn vpn) throws ResourceUnavailableException { + ExternalFirewallDeviceVO fwDeviceVO = getExternalFirewallForNetwork(network); + HostVO externalFirewall = _hostDao.findById(fwDeviceVO.getHostId()); + + if (externalFirewall == null) { + return false; + } + + // Create/delete VPN + IpAddress ip = _networkMgr.getIp(vpn.getServerAddressId()); + + // Mask the IP range with the network's VLAN tag + String[] ipRange = vpn.getIpRange().split("-"); + DataCenterVO zone = _dcDao.findById(network.getDataCenterId()); + int vlanTag = Integer.parseInt(network.getBroadcastUri().getHost()); + int offset = getVlanOffset(network.getPhysicalNetworkId(), vlanTag); + int cidrSize = getGloballyConfiguredCidrSize(); + + for (int i = 0; i < 2; i++) { + ipRange[i] = NetUtils.long2Ip((NetUtils.ip2Long(ipRange[i]) & 0xff000000) | (offset << (32 - cidrSize))); + } + + String maskedIpRange = ipRange[0] + "-" + ipRange[1]; + + RemoteAccessVpnCfgCommand createVpnCmd = new RemoteAccessVpnCfgCommand(create, ip.getAddress().addr(), vpn.getLocalIp(), maskedIpRange, vpn.getIpsecPresharedKey()); + createVpnCmd.setAccessDetail(NetworkElementCommand.ACCOUNT_ID, String.valueOf(network.getAccountId())); + createVpnCmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr()); + Answer answer = _agentMgr.easySend(externalFirewall.getId(), createVpnCmd); + if (answer == null || !answer.getResult()) { + String details = (answer != null) ? answer.getDetails() : "details unavailable"; + String msg = "External firewall was unable to create a remote access VPN in zone " + zone.getName() + " due to: " + details + "."; + s_logger.error(msg); + throw new ResourceUnavailableException(msg, DataCenter.class, zone.getId()); + } + + // Add/delete users + List vpnUsers = _vpnUsersDao.listByAccount(vpn.getAccountId()); + return manageRemoteAccessVpnUsers(network, vpn, vpnUsers); + } + + public boolean manageRemoteAccessVpnUsers(Network network, RemoteAccessVpn vpn, List vpnUsers) throws ResourceUnavailableException { + ExternalFirewallDeviceVO fwDeviceVO = getExternalFirewallForNetwork(network); + HostVO externalFirewall = _hostDao.findById(fwDeviceVO.getHostId()); + + if (externalFirewall == null) { + return false; + } + + List addUsers = new ArrayList(); + List removeUsers = new ArrayList(); + for (VpnUser user : vpnUsers) { + if (user.getState() == VpnUser.State.Add || + user.getState() == VpnUser.State.Active) { + addUsers.add(user); + } else if (user.getState() == VpnUser.State.Revoke) { + removeUsers.add(user); + } + } + + VpnUsersCfgCommand addUsersCmd = new VpnUsersCfgCommand(addUsers, removeUsers); + addUsersCmd.setAccessDetail(NetworkElementCommand.ACCOUNT_ID, String.valueOf(network.getAccountId())); + addUsersCmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr()); + + Answer answer = _agentMgr.easySend(externalFirewall.getId(), addUsersCmd); + if (answer == null || !answer.getResult()) { + String details = (answer != null) ? answer.getDetails() : "details unavailable"; + DataCenterVO zone = _dcDao.findById(network.getDataCenterId()); + String msg = "External firewall was unable to add remote access users in zone " + zone.getName() + " due to: " + details + "."; + s_logger.error(msg); + throw new ResourceUnavailableException(msg, DataCenter.class, zone.getId()); + } + + return true; + } + + public int getVlanOffset(long physicalNetworkId, int vlanTag) { + PhysicalNetworkVO pNetwork = _physicalNetworkDao.findById(physicalNetworkId); + if (pNetwork == null) { + throw new CloudRuntimeException("Could not find the physical Network " + physicalNetworkId + "."); + } + + if (pNetwork.getVnet() == null) { + throw new CloudRuntimeException("Could not find vlan range for physical Network " + physicalNetworkId + "."); + } + String vlanRange[] = pNetwork.getVnet().split("-"); + int lowestVlanTag = Integer.valueOf(vlanRange[0]); + return vlanTag - lowestVlanTag; + } + + private NicVO savePlaceholderNic(Network network, String ipAddress) { + NicVO nic = new NicVO(null, null, network.getId(), null); + nic.setIp4Address(ipAddress); + nic.setReservationStrategy(ReservationStrategy.PlaceHolder); + nic.setState(State.Reserved); + return _nicDao.persist(nic); + } + + public int getGloballyConfiguredCidrSize() { + try { + String globalVlanBits = _configDao.getValue(Config.GuestVlanBits.key()); + return 8 + Integer.parseInt(globalVlanBits); + } catch (Exception e) { + throw new CloudRuntimeException("Failed to read the globally configured VLAN bits size."); + } + } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, + Map details, List hostTags) { + if (!(startup[0] instanceof StartupExternalLoadBalancerCommand)) { + return null; + } + host.setType(Host.Type.ExternalFirewall); + return host; + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + // TODO Auto-generated method stub + return null; + } +} diff --git a/server/src/com/cloud/network/ExternalFirewallDeviceVO.java b/server/src/com/cloud/network/ExternalFirewallDeviceVO.java index 45297e54cb2..803f77ddbf3 100644 --- a/server/src/com/cloud/network/ExternalFirewallDeviceVO.java +++ b/server/src/com/cloud/network/ExternalFirewallDeviceVO.java @@ -18,6 +18,8 @@ package com.cloud.network; +import java.util.UUID; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; @@ -26,7 +28,6 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; -import com.cloud.network.PhysicalNetworkServiceProvider.State; /** * ExternalFirewallDeviceVO contains information of a external firewall device (Juniper SRX) added into a deployment @@ -40,6 +41,9 @@ public class ExternalFirewallDeviceVO { @Column(name = "id") private long id; + @Column(name="uuid") + private String uuid; + @Column(name = "host_id") private long hostId; @@ -49,35 +53,43 @@ public class ExternalFirewallDeviceVO { @Column(name = "provider_name") private String providerName; + @Column(name = "device_name") + private String deviceName; + @Column(name="state") @Enumerated(value=EnumType.STRING) - State state; + FirewallDeviceState state; @Column(name = "capacity") private long capacity; - @Column(name = "capacity_type") - private String capacity_type; - @Column(name = "allocation_state") @Enumerated(value=EnumType.STRING) - private AllocationState allocationState; + private FirewallDeviceAllocationState allocationState; - public enum AllocationState { + //keeping it enum for future possible states Maintenance, Shutdown + public enum FirewallDeviceState { + Enabled, + Disabled + } + + public enum FirewallDeviceAllocationState { Free, Allocated } - public ExternalFirewallDeviceVO(long hostId, long physicalNetworkId, String provider_name) { + public ExternalFirewallDeviceVO(long hostId, long physicalNetworkId, String provider_name, String device_name) { this.physicalNetworkId = physicalNetworkId; this.providerName = provider_name; + this.deviceName = device_name; this.hostId = hostId; - this.state = PhysicalNetworkServiceProvider.State.Disabled; - this.allocationState = AllocationState.Free; + this.state = FirewallDeviceState.Disabled; + this.allocationState = FirewallDeviceAllocationState.Free; + this.uuid = UUID.randomUUID().toString(); } public ExternalFirewallDeviceVO() { - + this.uuid = UUID.randomUUID().toString(); } public long getId() { @@ -92,6 +104,10 @@ public class ExternalFirewallDeviceVO { return providerName; } + public String getDeviceName() { + return deviceName; + } + public long getHostId() { return hostId; } @@ -100,23 +116,27 @@ public class ExternalFirewallDeviceVO { return capacity; } - public String getCapacityType() { - return capacity_type; - } - - public State getState() { + public FirewallDeviceState getState() { return state; } - public void setState(State state) { + public void setState(FirewallDeviceState state) { this.state = state; } - public AllocationState getAllocationState() { + public FirewallDeviceAllocationState getAllocationState() { return allocationState; } - public void setAllocationState(AllocationState allocationState) { + public void setAllocationState(FirewallDeviceAllocationState allocationState) { this.allocationState = allocationState; } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } } diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java new file mode 100644 index 00000000000..8523386630f --- /dev/null +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java @@ -0,0 +1,100 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.network; + +import java.util.List; + +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.host.Host; +import com.cloud.network.rules.FirewallRule; +import com.cloud.resource.ServerResource; +import com.cloud.utils.component.Manager; + +/* ExternalLoadBalancerDeviceManager provides a abstract implementation for managing a external load balancer in device agnostic manner. + * Device specific managers for external load balancers (like F5 and Netscaler) should be implemented as pluggable service extending + * ExternalLoadBalancerDeviceManager implementation. An implementation of device specific manager can override default behaviour if needed. + */ + +public interface ExternalLoadBalancerDeviceManager extends Manager{ + + /** + * adds a load balancer device in to a physical network + * @param physicalNetworkId physical network id of the network in to which device to be added + * @param url url encoding device IP and device configuration parameter + * @param username username + * @param password password + * @param deviceName device name + * @param server resource that will handle the commands specific to this device + * @return Host object for the device added + */ + public ExternalLoadBalancerDeviceVO addExternalLoadBalancer(long physicalNetworkId, String url, String username, String password, String deviceName, ServerResource resource); + + /** + * deletes load balancer device added in to a physical network + * @param hostId + * @return true if device successfully deleted + */ + public boolean deleteExternalLoadBalancer(long hostId); + + /** + * list external load balancers of given device name type added in to a physical network + * @param physicalNetworkId + * @param deviceName + * @return list of host objects for the external load balancers added in to the physical network + */ + public List listExternalLoadBalancers(long physicalNetworkId, String deviceName); + + /** + * finds a suitable load balancer device which can be used by this network + * @param network guest network + * @param dedicatedLb true if a dedicated load balancer is needed for this guest network + * @return ExternalLoadBalancerDeviceVO corresponding to the suitable device + * @throws InsufficientCapacityException + */ + public ExternalLoadBalancerDeviceVO findSuitableLoadBalancerForNetwork(Network network, boolean dedicatedLb) throws InsufficientCapacityException; + + /** + * returns the load balancer device allocated for the guest network + * @param network guest network id + * @return ExternalLoadBalancerDeviceVO object corresponding the load balancer device assigned for this guest network + */ + public ExternalLoadBalancerDeviceVO getExternalLoadBalancerForNetwork(Network network); + + /** + * applies load balancer rules + * @param network guest network if + * @param rules load balancer rules + * @return true if successfully applied rules + * @throws ResourceUnavailableException + */ + public boolean applyLoadBalancerRules(Network network, List rules) throws ResourceUnavailableException; + + /** + * implements or shutdowns guest network on the load balancer device assigned to the guest network + * @param add + * @param guestConfig + * @return + * @throws ResourceUnavailableException + * @throws InsufficientCapacityException + */ + public boolean manageGuestNetworkWithExternalLoadBalancer(boolean add, Network guestConfig) throws ResourceUnavailableException, InsufficientCapacityException; + +} diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java new file mode 100644 index 00000000000..3d4326326c8 --- /dev/null +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java @@ -0,0 +1,1071 @@ +/** + * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +* + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.network; + +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer; +import com.cloud.agent.api.ExternalNetworkResourceUsageCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupExternalLoadBalancerCommand; +import com.cloud.agent.api.routing.CreateLBApplianceCommand; +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.routing.SetStaticNatRulesCommand; +import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.agent.api.to.LoadBalancerTO; +import com.cloud.agent.api.to.StaticNatRuleTO; +import com.cloud.api.ApiConstants; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.VlanVO; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.VlanDao; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InsufficientNetworkCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.host.DetailVO; +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.ExternalLoadBalancerDeviceVO.LBDeviceAllocationState; +import com.cloud.network.ExternalLoadBalancerDeviceVO.LBDeviceState; +import com.cloud.network.ExternalNetworkDeviceManager.NetworkDevice; +import com.cloud.network.Network.Capability; +import com.cloud.network.Network.Service; +import com.cloud.network.Networks.TrafficType; +import com.cloud.network.dao.ExternalLoadBalancerDeviceDao; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.network.dao.InlineLoadBalancerNicMapDao; +import com.cloud.network.dao.LoadBalancerDao; +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.dao.PhysicalNetworkServiceProviderDao; +import com.cloud.network.dao.PhysicalNetworkServiceProviderVO; +import com.cloud.network.lb.LoadBalancingRule; +import com.cloud.network.lb.LoadBalancingRule.LbDestination; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.FirewallRuleVO; +import com.cloud.network.rules.PortForwardingRuleVO; +import com.cloud.network.rules.StaticNatRule; +import com.cloud.network.rules.StaticNatRuleImpl; +import com.cloud.network.rules.FirewallRule.Purpose; +import com.cloud.network.rules.dao.PortForwardingRulesDao; +import com.cloud.offerings.NetworkOfferingVO; +import com.cloud.offerings.dao.NetworkOfferingDao; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceStateAdapter; +import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; +import com.cloud.server.api.response.ExternalLoadBalancerResponse; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountVO; +import com.cloud.user.UserStatisticsVO; +import com.cloud.user.dao.AccountDao; +import com.cloud.user.dao.UserStatisticsDao; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.component.AdapterBase; +import com.cloud.utils.component.Inject; +import com.cloud.utils.concurrency.NamedThreadFactory; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.GlobalLock; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.exception.ExecutionException; +import com.cloud.utils.net.NetUtils; +import com.cloud.utils.net.UrlUtil; +import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.NicVO; +import com.cloud.vm.Nic.ReservationStrategy; +import com.cloud.vm.Nic.State; +import com.cloud.vm.dao.DomainRouterDao; +import com.cloud.vm.dao.NicDao; + +public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase implements ExternalLoadBalancerDeviceManager, ResourceStateAdapter { + + @Inject NetworkExternalLoadBalancerDao _networkExternalLBDao; + @Inject ExternalLoadBalancerDeviceDao _externalLoadBalancerDeviceDao; + @Inject HostDao _hostDao; + @Inject DataCenterDao _dcDao; + @Inject HostDetailsDao _detailsDao; + @Inject NetworkManager _networkMgr; + @Inject InlineLoadBalancerNicMapDao _inlineLoadBalancerNicMapDao; + @Inject NicDao _nicDao; + @Inject AgentManager _agentMgr; + @Inject ResourceManager _resourceMgr; + @Inject IPAddressDao _ipAddressDao; + @Inject VlanDao _vlanDao; + @Inject NetworkOfferingDao _networkOfferingDao; + @Inject AccountDao _accountDao; + @Inject PhysicalNetworkDao _physicalNetworkDao; + @Inject PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao; + @Inject AccountManager _accountMgr; + @Inject UserStatisticsDao _userStatsDao; + @Inject NetworkDao _networkDao; + @Inject DomainRouterDao _routerDao; + @Inject LoadBalancerDao _loadBalancerDao; + @Inject PortForwardingRulesDao _portForwardingRulesDao; + @Inject ConfigurationDao _configDao; + @Inject HostDetailsDao _hostDetailDao; + @Inject NetworkExternalLoadBalancerDao _networkLBDao; + @Inject NetworkServiceMapDao _ntwkSrvcProviderDao; + + ScheduledExecutorService _executor; + int _externalNetworkStatsInterval; + protected String _name; + private static final org.apache.log4j.Logger s_logger = Logger.getLogger(ExternalLoadBalancerDeviceManagerImpl.class); + + @Override + @DB + public ExternalLoadBalancerDeviceVO addExternalLoadBalancer(long physicalNetworkId, String url, String username, String password, String deviceName, ServerResource resource) { + + String guid; + PhysicalNetworkVO pNetwork=null; + NetworkDevice ntwkDevice = NetworkDevice.getNetworkDevice(deviceName); + long zoneId; + + if ((ntwkDevice == null) || (url == null) || (username == null) || (resource == null) || (password == null) ) { + throw new InvalidParameterValueException("Atleast one of the required parameters (url, username, password," + + " server resource, zone id/physical network id) is not specified or a valid parameter."); + } + + pNetwork = _physicalNetworkDao.findById(physicalNetworkId); + if (pNetwork == null) { + throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId); + } + zoneId = pNetwork.getDataCenterId(); + + PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), ntwkDevice.getNetworkServiceProvder()); + if (ntwkSvcProvider == null ) { + throw new CloudRuntimeException("Network Service Provider: " + ntwkDevice.getNetworkServiceProvder() + + " is not enabled in the physical network: " + physicalNetworkId + "to add this device" ); + } else if ((ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) + || (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Disabled)) { + throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() + + " is not added or in shutdown state in the physical network: " + physicalNetworkId + "to add this device" ); + } + + URI uri; + try { + uri = new URI(url); + } catch (Exception e) { + s_logger.debug(e); + throw new InvalidParameterValueException(e.getMessage()); + } + + String ipAddress = uri.getHost(); + Map hostDetails = new HashMap(); + guid = getExternalNetworkResourceGuid(pNetwork.getId(), deviceName, ipAddress); + hostDetails.put("guid", guid); + hostDetails.put("zoneId", String.valueOf(pNetwork.getDataCenterId())); + hostDetails.put("ip", ipAddress); + hostDetails.put("physicalNetworkId", String.valueOf(pNetwork.getId())); + hostDetails.put("username", username); + hostDetails.put("password", password); + hostDetails.put("deviceName", deviceName); + + // leave parameter validation to be part server resource configure + Map params = new HashMap(); + UrlUtil.parseQueryParameters(uri.getQuery(), false, params); + hostDetails.putAll(params); + + try { + resource.configure(guid, hostDetails); + + Host host = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalLoadBalancer, hostDetails); + if (host != null) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + + ExternalLoadBalancerDeviceVO lbDeviceVO = new ExternalLoadBalancerDeviceVO(host.getId(), pNetwork.getId(), ntwkSvcProvider.getProviderName(), deviceName); + _externalLoadBalancerDeviceDao.persist(lbDeviceVO); + + DetailVO hostDetail = new DetailVO(host.getId(), ApiConstants.LOAD_BALANCER_DEVICE_ID, String.valueOf(lbDeviceVO.getId())); + _hostDetailDao.persist(hostDetail); + + txn.commit(); + return lbDeviceVO; + } else { + throw new CloudRuntimeException("Failed to add load balancer device due to internal error."); + } + } catch (ConfigurationException e) { + throw new CloudRuntimeException(e.getMessage()); + } + } + + @Override + public boolean deleteExternalLoadBalancer(long hostId) { + HostVO externalLoadBalancer = _hostDao.findById(hostId); + if (externalLoadBalancer == null) { + throw new InvalidParameterValueException("Could not find an external load balancer with ID: " + hostId); + } + + DetailVO lbHostDetails = _hostDetailDao.findDetail(hostId, ApiConstants.LOAD_BALANCER_DEVICE_ID); + long lbDeviceId = Long.parseLong(lbHostDetails.getValue()); + + // check if any networks are using this load balancer device + List networks = _networkLBDao.listByLoadBalancerDeviceId(lbDeviceId); + if ((networks != null) && !networks.isEmpty()) { + throw new CloudRuntimeException("Delete can not be done as there are networks using this load balancer device "); + } + + try { + if (_resourceMgr.maintain(hostId) && _resourceMgr.deleteHost(hostId, false, false)) { + DataCenterVO zone = _dcDao.findById(externalLoadBalancer.getDataCenterId()); + return _dcDao.update(zone.getId(), zone); + } else { + return false; + } + } catch (AgentUnavailableException e) { + s_logger.debug(e); + return false; + } + } + + @Override + public List listExternalLoadBalancers(long physicalNetworkId, String deviceName) { + List lbHosts = new ArrayList(); + NetworkDevice lbNetworkDevice = NetworkDevice.getNetworkDevice(deviceName); + PhysicalNetworkVO pNetwork=null; + + pNetwork = _physicalNetworkDao.findById(physicalNetworkId); + + if ((pNetwork == null) || (lbNetworkDevice == null)) { + throw new InvalidParameterValueException("Atleast one of the required parameter physical networkId, device name is invalid."); + } + + PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), + lbNetworkDevice.getNetworkServiceProvder()); + //if provider not configured in to physical network, then there can be no instances + if (ntwkSvcProvider == null) { + return null; + } + + List lbDevices = _externalLoadBalancerDeviceDao.listByPhysicalNetworkAndProvider(physicalNetworkId, + ntwkSvcProvider.getProviderName()); + for (ExternalLoadBalancerDeviceVO provderInstance : lbDevices) { + lbHosts.add(_hostDao.findById(provderInstance.getHostId())); + } + return lbHosts; + } + + public ExternalLoadBalancerResponse createExternalLoadBalancerResponse(Host externalLoadBalancer) { + Map lbDetails = _detailsDao.findDetails(externalLoadBalancer.getId()); + ExternalLoadBalancerResponse response = new ExternalLoadBalancerResponse(); + response.setId(externalLoadBalancer.getId()); + response.setIpAddress(externalLoadBalancer.getPrivateIpAddress()); + response.setUsername(lbDetails.get("username")); + response.setPublicInterface(lbDetails.get("publicInterface")); + response.setPrivateInterface(lbDetails.get("privateInterface")); + response.setNumRetries(lbDetails.get("numRetries")); + return response; + } + + public String getExternalNetworkResourceGuid(long physicalNetworkId, String deviceName, String ip) { + return physicalNetworkId + "-" + deviceName + "-" + ip; + } + + @Override + public ExternalLoadBalancerDeviceVO findSuitableLoadBalancerForNetwork(Network network, boolean dedicatedLb) throws InsufficientCapacityException { + long physicalNetworkId = network.getPhysicalNetworkId(); + List lbDevices =null; + String provider = _ntwkSrvcProviderDao.getProviderForServiceInNetwork(network.getId(), Service.Lb); + assert(provider != null); + + if (dedicatedLb) { + lbDevices = _externalLoadBalancerDeviceDao.listByProviderAndDeviceAllocationState(physicalNetworkId, provider, LBDeviceAllocationState.Free); + if (lbDevices != null && !lbDevices.isEmpty()) { + + //return first device that is free, fully configured and meant for dedicated use + for (ExternalLoadBalancerDeviceVO lbdevice : lbDevices) { + if (lbdevice.getState() == LBDeviceState.Enabled && lbdevice.getIsDedicatedDevice()) { + return lbdevice; + } + } + + //if there are no dedicated lb device then return first device that is free, fully configured + for (ExternalLoadBalancerDeviceVO lbdevice : lbDevices) { + if (lbdevice.getState() == LBDeviceState.Enabled) { + return lbdevice; + } + } + } + } else { + // get the LB devices that are already allocated for shared use + lbDevices = _externalLoadBalancerDeviceDao.listByProviderAndDeviceAllocationState(physicalNetworkId, provider, LBDeviceAllocationState.Shared); + + if (lbDevices != null) { + + ExternalLoadBalancerDeviceVO maxFreeCapacityLbdevice = null; + long maxFreeCapacity = 0; + + // loop through the LB device in the physical network and pick the one with maximum free capacity + for (ExternalLoadBalancerDeviceVO lbdevice: lbDevices) { + + // skip if device is not enabled + if (lbdevice.getState() != LBDeviceState.Enabled) { + continue; + } + + // skip if the device is intended to be used in dedicated mode only + if (lbdevice.getIsDedicatedDevice()) { + continue; + } + + List mappedNetworks = _networkExternalLBDao.listByLoadBalancerDeviceId(lbdevice.getId()); + // get the list of guest networks that are mapped to this load balancer + long usedCapacity = ((mappedNetworks == null) || (mappedNetworks.isEmpty()))? 0 : mappedNetworks.size(); + // get max number of guest networks that can be mapped to this device + long fullCapacity = lbdevice.getCapacity(); + + long freeCapacity = fullCapacity - usedCapacity; + if (freeCapacity > 0) { + if (maxFreeCapacityLbdevice == null) { + maxFreeCapacityLbdevice = lbdevice; + maxFreeCapacity = freeCapacity; + } + if (freeCapacity > maxFreeCapacity) { + maxFreeCapacityLbdevice = lbdevice; + maxFreeCapacity = freeCapacity; + } + } + } + } + + // if we are here then there are no existing LB devices in shared use or the devices in shared use has no free capacity + // so allocate a new one from the pool of free LB devices + lbDevices = _externalLoadBalancerDeviceDao.listByProviderAndDeviceAllocationState(physicalNetworkId, provider, LBDeviceAllocationState.Free); + if (lbDevices != null && !lbDevices.isEmpty()) { + for (ExternalLoadBalancerDeviceVO lbdevice : lbDevices) { + if (lbdevice.getState() == LBDeviceState.Enabled && !lbdevice.getIsDedicatedDevice()) { + return lbdevice; + } + } + } + } + + throw new InsufficientNetworkCapacityException("Unable to find a load balancing provider with sufficient capcity " + + " to implement the network", Network.class, network.getId()); + } + + HostVO getFirewallProviderForNetwork(Network network) { + String fwProvider = _ntwkSrvcProviderDao.getProviderForServiceInNetwork(network.getId(), Service.Firewall); + + if (fwProvider.equalsIgnoreCase("VirtualRouter")) { + //FIXME: get the host Id of the host on which the virtual router is running + } else { + //FIXME: external firewall host object + } + + return null; + } + + @Override + public ExternalLoadBalancerDeviceVO getExternalLoadBalancerForNetwork(Network network) { + NetworkExternalLoadBalancerVO lbDeviceForNetwork = _networkExternalLBDao.findByNetworkId(network.getId()); + if (lbDeviceForNetwork != null) { + long lbDeviceId = lbDeviceForNetwork.getExternalLBDeviceId(); + ExternalLoadBalancerDeviceVO lbDeviceVo = _externalLoadBalancerDeviceDao.findById(lbDeviceId); + assert(lbDeviceVo != null); + } + return null; + } + + public void setExternalLoadBalancerForNetwork(Network network, long externalLBDeviceID) { + NetworkExternalLoadBalancerVO lbDeviceForNetwork = new NetworkExternalLoadBalancerVO(network.getId(), externalLBDeviceID); + _networkExternalLBDao.persist(lbDeviceForNetwork); + } + + private boolean externalLoadBalancerIsInline(HostVO externalLoadBalancer) { + DetailVO detail = _detailsDao.findDetail(externalLoadBalancer.getId(), "inline"); + return (detail != null && detail.getValue().equals("true")); + } + + private NicVO savePlaceholderNic(Network network, String ipAddress) { + NicVO nic = new NicVO(null, null, network.getId(), null); + nic.setIp4Address(ipAddress); + nic.setReservationStrategy(ReservationStrategy.PlaceHolder); + nic.setState(State.Reserved); + return _nicDao.persist(nic); + } + + private void applyStaticNatRuleForInlineLBRule(DataCenterVO zone, Network network, HostVO firewallHost, boolean revoked, String publicIp, String privateIp) throws ResourceUnavailableException { + List staticNatRules = new ArrayList(); + IPAddressVO ipVO = _ipAddressDao.listByDcIdIpAddress(zone.getId(), publicIp).get(0); + VlanVO vlan = _vlanDao.findById(ipVO.getVlanId()); + FirewallRuleVO fwRule = new FirewallRuleVO(null, ipVO.getId(), -1, -1, "any", network.getId(), network.getAccountId(), network.getDomainId(), Purpose.StaticNat, null, null, null, null); + FirewallRule.State state = !revoked ? FirewallRule.State.Add : FirewallRule.State.Revoke; + fwRule.setState(state); + StaticNatRule rule = new StaticNatRuleImpl(fwRule, privateIp); + StaticNatRuleTO ruleTO = new StaticNatRuleTO(rule, vlan.getVlanTag(), publicIp, privateIp); + staticNatRules.add(ruleTO); + + applyStaticNatRules(staticNatRules, network, firewallHost.getId()); + } + + protected void applyStaticNatRules(List staticNatRules, Network network, long firewallHostId) throws ResourceUnavailableException { + if (!staticNatRules.isEmpty()) { + SetStaticNatRulesCommand cmd = new SetStaticNatRulesCommand(staticNatRules); + Answer answer = _agentMgr.easySend(firewallHostId, cmd); + if (answer == null || !answer.getResult()) { + String details = (answer != null) ? answer.getDetails() : "details unavailable"; + String msg = "firewall provider for the network was unable to apply static nat rules due to: " + details + "."; + s_logger.error(msg); + throw new ResourceUnavailableException(msg, Network.class, network.getId()); + } + } + } + + @Override + public boolean applyLoadBalancerRules(Network network, List rules) throws ResourceUnavailableException { + // Find the external load balancer in this zone + long zoneId = network.getDataCenterId(); + DataCenterVO zone = _dcDao.findById(zoneId); + + ExternalLoadBalancerDeviceVO lbDeviceVO = getExternalLoadBalancerForNetwork(network); + assert(lbDeviceVO != null) : "There is no device assigned to this network how apply rules ended up here??"; + HostVO externalLoadBalancer = _hostDao.findById(lbDeviceVO.getHostId()); + + boolean externalLoadBalancerIsInline = externalLoadBalancerIsInline(externalLoadBalancer); + + if (network.getState() == Network.State.Allocated) { + s_logger.debug("External load balancer was asked to apply LB rules for network with ID " + network.getId() + "; this network is not implemented. Skipping backend commands."); + return true; + } + + List loadBalancingRules = new ArrayList(); + + for (FirewallRule rule : rules) { + if (rule.getPurpose().equals(Purpose.LoadBalancing)) { + loadBalancingRules.add((LoadBalancingRule) rule); + } + } + + List loadBalancersToApply = new ArrayList(); + for (int i = 0; i < loadBalancingRules.size(); i++) { + LoadBalancingRule rule = loadBalancingRules.get(i); + + boolean revoked = (rule.getState().equals(FirewallRule.State.Revoke)); + String protocol = rule.getProtocol(); + String algorithm = rule.getAlgorithm(); + String srcIp = _networkMgr.getIp(rule.getSourceIpAddressId()).getAddress().addr(); + int srcPort = rule.getSourcePortStart(); + List destinations = rule.getDestinations(); + List sourceCidrs = rule.getSourceCidrList(); + + if (externalLoadBalancerIsInline) { + InlineLoadBalancerNicMapVO mapping = _inlineLoadBalancerNicMapDao.findByPublicIpAddress(srcIp); + NicVO loadBalancingIpNic = null; + HostVO firewallProviderHost = null; + + if (externalLoadBalancerIsInline) { + firewallProviderHost = getFirewallProviderForNetwork(network); + } + + if (!revoked) { + if (mapping == null) { + // Acquire a new guest IP address and save it as the load balancing IP address + String loadBalancingIpAddress = _networkMgr.acquireGuestIpAddress(network, null); + + if (loadBalancingIpAddress == null) { + String msg = "Ran out of guest IP addresses."; + s_logger.error(msg); + throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId()); + } + + // If a NIC doesn't exist for the load balancing IP address, create one + loadBalancingIpNic = _nicDao.findByIp4Address(loadBalancingIpAddress); + if (loadBalancingIpNic == null) { + loadBalancingIpNic = savePlaceholderNic(network, loadBalancingIpAddress); + } + + // Save a mapping between the source IP address and the load balancing IP address NIC + mapping = new InlineLoadBalancerNicMapVO(rule.getId(), srcIp, loadBalancingIpNic.getId()); + _inlineLoadBalancerNicMapDao.persist(mapping); + + // On the firewall provider for the network, create a static NAT rule between the source IP address and the load balancing IP address + applyStaticNatRuleForInlineLBRule(zone, network, firewallProviderHost, revoked, srcIp, loadBalancingIpNic.getIp4Address()); + } else { + loadBalancingIpNic = _nicDao.findById(mapping.getNicId()); + } + } else { + if (mapping != null) { + // Find the NIC that the mapping refers to + loadBalancingIpNic = _nicDao.findById(mapping.getNicId()); + + // On the firewall provider for the network, delete the static NAT rule between the source IP address and the load balancing IP address + applyStaticNatRuleForInlineLBRule(zone, network, firewallProviderHost, revoked, srcIp, loadBalancingIpNic.getIp4Address()); + + // Delete the mapping between the source IP address and the load balancing IP address + _inlineLoadBalancerNicMapDao.expunge(mapping.getId()); + + // Delete the NIC + _nicDao.expunge(loadBalancingIpNic.getId()); + } else { + s_logger.debug("Revoking a rule for an inline load balancer that has not been programmed yet."); + continue; + } + } + + // Change the source IP address for the load balancing rule to be the load balancing IP address + srcIp = loadBalancingIpNic.getIp4Address(); + } + + if (destinations != null && !destinations.isEmpty()) { + LoadBalancerTO loadBalancer = new LoadBalancerTO(srcIp, srcPort, protocol, algorithm, revoked, false, destinations); + loadBalancersToApply.add(loadBalancer); + } + } + + if (loadBalancersToApply.size() > 0) { + int numLoadBalancersForCommand = loadBalancersToApply.size(); + LoadBalancerTO[] loadBalancersForCommand = loadBalancersToApply.toArray(new LoadBalancerTO[numLoadBalancersForCommand]); + LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(loadBalancersForCommand); + long guestVlanTag = Integer.parseInt(network.getBroadcastUri().getHost()); + cmd.setAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG, String.valueOf(guestVlanTag)); + Answer answer = _agentMgr.easySend(externalLoadBalancer.getId(), cmd); + if (answer == null || !answer.getResult()) { + String details = (answer != null) ? answer.getDetails() : "details unavailable"; + String msg = "Unable to apply load balancer rules to the external load balancer appliance in zone " + zone.getName() + " due to: " + details + "."; + s_logger.error(msg); + throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId()); + } + } + + return true; + } + + @Override + @DB + public boolean manageGuestNetworkWithExternalLoadBalancer(boolean add, Network guestConfig) throws ResourceUnavailableException, InsufficientCapacityException { + if (guestConfig.getTrafficType() != TrafficType.Guest) { + s_logger.trace("External load balancer can only be user for guest networks."); + return false; + } + + long zoneId = guestConfig.getDataCenterId(); + DataCenterVO zone = _dcDao.findById(zoneId); + HostVO externalLoadBalancer = null; + String provider = _ntwkSrvcProviderDao.getProviderForServiceInNetwork(guestConfig.getId(), Service.Lb); + long physicalNetworkId = guestConfig.getPhysicalNetworkId(); + + if (add) { + boolean retry = true; + boolean provisionLB = false; + + while (retry) { + GlobalLock deviceMapLock = GlobalLock.getInternLock("LoadBalancerAllocLock"); + Transaction txn = Transaction.currentTxn(); + try { + if (deviceMapLock.lock(120)) { + try { + NetworkOfferingVO offering = _networkOfferingDao.findById(guestConfig.getNetworkOfferingId()); + long lbDeviceId; + txn.start(); + + // FIXME: should the device allocation be done during network implement phase or do a lazy allocation + // when first rule for the network is configured?? + + // find a load balancer device as per the network offering + boolean dedicatedLB = offering.getDedicatedLB(); + try { + ExternalLoadBalancerDeviceVO lbDevice = findSuitableLoadBalancerForNetwork(guestConfig, dedicatedLB); + lbDeviceId = lbDevice.getId(); + + // persist the load balancer device id that will be used for this network. Once a network + // is implemented on a LB device then later on all rules will be programmed on to same device + NetworkExternalLoadBalancerVO networkLB = new NetworkExternalLoadBalancerVO(guestConfig.getId(), lbDeviceId); + _networkExternalLBDao.persist(networkLB); + + // mark device to be in use + lbDevice.setAllocationState(dedicatedLB ? LBDeviceAllocationState.Dedicated : LBDeviceAllocationState.Shared); + _externalLoadBalancerDeviceDao.update(lbDeviceId, lbDevice); + + // return the HostVO for the lb device + externalLoadBalancer = _hostDao.findById(lbDevice.getHostId()); + txn.commit(); + + // got the load balancer for the network, so skip retry + provisionLB = false; + retry = false; + } catch (InsufficientCapacityException exception) { + if (provisionLB) { + retry = false; + throw exception; // if already attempted once throw out of capacity exception + } + provisionLB = true; // if possible provision a LB appliance in the physical network + } + } finally { + deviceMapLock.unlock(); + if (externalLoadBalancer == null) { + txn.rollback(); + } + } + } + } finally { + deviceMapLock.releaseRef(); + } + + // there are no LB devices or there is no free capacity on the devices in the physical network so provision a new LB appliance + if (provisionLB) { + // check if LB appliance can be dynamically provisioned + List providerLbDevices = _externalLoadBalancerDeviceDao.listByProviderAndDeviceAllocationState(physicalNetworkId, provider, LBDeviceAllocationState.Provider); + if ((providerLbDevices != null) && (!providerLbDevices.isEmpty())) { + for (ExternalLoadBalancerDeviceVO lbProviderDevice : providerLbDevices) { + if (lbProviderDevice.getState() == LBDeviceState.Enabled) { + // acquire a private IP needed for LB appliance to be provisioned + // TODO: get the ip from the pool of private IP's configured for physical network + String lbIP = null; + + //TODO: get the configuration details needed to provision LB instances + String username = null; + String password = null; + String publiInterface = null; + String privateInterface = null; + + // send CreateLBApplianceCommand to the host capable of provisioning + CreateLBApplianceCommand lbProvisionCmd = new CreateLBApplianceCommand(lbIP); + Answer answer = _agentMgr.easySend(lbProviderDevice.getHostId(), lbProvisionCmd); + + if (answer == null || !answer.getResult()) { + s_logger.trace("Could not provision load balancer instance on the load balancer device " + lbProviderDevice.getId()); + continue; + } + + //add the appliance as external load balancer + //addExternalLoadBalancer(); + //add the appliance to pool of the load balancers + } + } + } + } + } + } else { + // find the load balancer device allocated for the network + ExternalLoadBalancerDeviceVO lbDeviceVO = getExternalLoadBalancerForNetwork(guestConfig); + assert(lbDeviceVO != null) : "There is no device assigned to this network how did shutdown network ended up here??"; + externalLoadBalancer = _hostDao.findById(lbDeviceVO.getHostId()); + assert (externalLoadBalancer != null) : "There is no device assigned to this network how did shutdown network ended up here??"; + } + + // Send a command to the external load balancer to implement or shutdown the guest network + long guestVlanTag = Long.parseLong(guestConfig.getBroadcastUri().getHost()); + String selfIp = NetUtils.long2Ip(NetUtils.ip2Long(guestConfig.getGateway()) + 1); + String guestVlanNetmask = NetUtils.cidr2Netmask(guestConfig.getCidr()); + Integer networkRate = _networkMgr.getNetworkRate(guestConfig.getId(), null); + + IpAddressTO ip = new IpAddressTO(guestConfig.getAccountId(), null, add, false, true, String.valueOf(guestVlanTag), selfIp, guestVlanNetmask, null, null, networkRate, false); + IpAddressTO[] ips = new IpAddressTO[1]; + ips[0] = ip; + IpAssocCommand cmd = new IpAssocCommand(ips); + Answer answer = _agentMgr.easySend(externalLoadBalancer.getId(), cmd); + + if (answer == null || !answer.getResult()) { + String action = add ? "implement" : "shutdown"; + String answerDetails = (answer != null) ? answer.getDetails() : "answer was null"; + String msg = "External load balancer was unable to " + action + " the guest network on the external load balancer in zone " + zone.getName() + " due to " + answerDetails; + s_logger.error(msg); + throw new ResourceUnavailableException(msg, DataCenter.class, zoneId); + } + + List reservedIpAddressesForGuestNetwork = _nicDao.listIpAddressInNetwork(guestConfig.getId()); + if (add && (!reservedIpAddressesForGuestNetwork.contains(selfIp))) { + // Insert a new NIC for this guest network to reserve the self IP + savePlaceholderNic(guestConfig, selfIp); + } + + if (!add) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + + // since network is shutdown remove the network mapping to the load balancer device + NetworkExternalLoadBalancerVO networkLBDevice = _networkExternalLBDao.findByNetworkId(guestConfig.getId()); + _networkExternalLBDao.remove(networkLBDevice.getId()); + + // if this is the last network mapped to the load balancer device then set device allocation state to be free + List ntwksMapped = _networkExternalLBDao.listByLoadBalancerDeviceId(networkLBDevice.getExternalLBDeviceId()); + if (ntwksMapped == null || ntwksMapped.isEmpty()) { + ExternalLoadBalancerDeviceVO lbDevice = _externalLoadBalancerDeviceDao.findById(networkLBDevice.getExternalLBDeviceId()); + lbDevice.setAllocationState(LBDeviceAllocationState.Free); + _externalLoadBalancerDeviceDao.update(lbDevice.getId(), lbDevice); + + //TODO: if device is cloud managed then take action + } + txn.commit(); + } + + Account account = _accountDao.findByIdIncludingRemoved(guestConfig.getAccountId()); + String action = add ? "implemented" : "shut down"; + s_logger.debug("External load balancer has " + action + " the guest network for account " + account.getAccountName() + "(id = " + account.getAccountId() + ") with VLAN tag " + guestVlanTag); + + return true; + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + _name = name; + _externalNetworkStatsInterval = NumbersUtil.parseInt(_configDao.getValue(Config.RouterStatsInterval.key()), 300); + if (_externalNetworkStatsInterval > 0){ + _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("ExternalNetworkMonitor")); + } + + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); + return true; + } + + @Override + public boolean start() { + if (_externalNetworkStatsInterval > 0){ + _executor.scheduleAtFixedRate(new ExternalLoadBalancerDeviceNetworkUsageTask(), _externalNetworkStatsInterval, _externalNetworkStatsInterval, TimeUnit.SECONDS); + } + return true; + } + + @Override + public boolean stop() { + return true; + } + + protected class ExternalLoadBalancerDeviceNetworkUsageTask implements Runnable { + + public ExternalLoadBalancerDeviceNetworkUsageTask() { + + } + + @Override + public void run() { + GlobalLock scanLock = GlobalLock.getInternLock("ExternalLoadBalancerDeviceManagerImpl"); + try { + if (scanLock.lock(20)) { + try { + runExternalLoadBalancerNetworkUsageTask(); + } finally { + scanLock.unlock(); + } + } + } catch (Exception e) { + s_logger.warn("Problems while getting external network usage", e); + } finally { + scanLock.releaseRef(); + } + } + + private void runExternalLoadBalancerNetworkUsageTask() { + s_logger.debug("External load balancer devices stats collector is running..."); + + for (DataCenterVO zone : _dcDao.listAll()) { + List domainRoutersInZone = _routerDao.listByDataCenter(zone.getId()); + for (DomainRouterVO domainRouter : domainRoutersInZone) { + long accountId = domainRouter.getAccountId(); + long zoneId = zone.getId(); + List networksForAccount = _networkDao.listBy(accountId, zoneId, Network.GuestType.Isolated); + + for (NetworkVO network : networksForAccount) { + if (!_networkMgr.networkIsConfiguredForExternalNetworking(zoneId, network.getId())) { + s_logger.debug("Network " + network.getId() + " is not configured for external networking, so skipping usage check."); + continue; + } + + HostVO externalFirewall = getFirewallProviderForNetwork(network); + ExternalLoadBalancerDeviceVO lbDeviceVO = getExternalLoadBalancerForNetwork(network); + assert(lbDeviceVO != null); + HostVO externalLoadBalancer = _hostDao.findById(lbDeviceVO.getHostId()); + s_logger.debug("Collecting external network stats for network " + network.getId()); + + ExternalNetworkResourceUsageCommand cmd = new ExternalNetworkResourceUsageCommand(); + + // Get network stats from the external firewall + ExternalNetworkResourceUsageAnswer firewallAnswer = null; + if (externalFirewall != null) { + firewallAnswer = (ExternalNetworkResourceUsageAnswer) _agentMgr.easySend(externalFirewall.getId(), cmd); + if (firewallAnswer == null || !firewallAnswer.getResult()) { + String details = (firewallAnswer != null) ? firewallAnswer.getDetails() : "details unavailable"; + String msg = "Unable to get external firewall stats for " + zone.getName() + " due to: " + details + "."; + s_logger.error(msg); + continue; + } + } + + // Get network stats from the external load balancer + ExternalNetworkResourceUsageAnswer lbAnswer = null; + if (externalLoadBalancer != null) { + lbAnswer = (ExternalNetworkResourceUsageAnswer) _agentMgr.easySend(externalLoadBalancer.getId(), cmd); + if (lbAnswer == null || !lbAnswer.getResult()) { + String details = (lbAnswer != null) ? lbAnswer.getDetails() : "details unavailable"; + String msg = "Unable to get external load balancer stats for " + zone.getName() + " due to: " + details + "."; + s_logger.error(msg); + } + } + + AccountVO account = _accountDao.findById(accountId); + if (account == null) { + s_logger.debug("Skipping stats update for account with ID " + accountId); + continue; + } + + if (!manageStatsEntries(true, accountId, zoneId, network, externalFirewall, firewallAnswer, externalLoadBalancer, lbAnswer)) { + continue; + } + + manageStatsEntries(false, accountId, zoneId, network, externalFirewall, firewallAnswer, externalLoadBalancer, lbAnswer); + } + } + } + } + + private boolean updateBytes(UserStatisticsVO userStats, long newCurrentBytesSent, long newCurrentBytesReceived) { + long oldNetBytesSent = userStats.getNetBytesSent(); + long oldNetBytesReceived = userStats.getNetBytesReceived(); + long oldCurrentBytesSent = userStats.getCurrentBytesSent(); + long oldCurrentBytesReceived = userStats.getCurrentBytesReceived(); + String warning = "Received an external network stats byte count that was less than the stored value. Zone ID: " + userStats.getDataCenterId() + ", account ID: " + userStats.getAccountId() + "."; + + userStats.setCurrentBytesSent(newCurrentBytesSent); + if (oldCurrentBytesSent > newCurrentBytesSent) { + s_logger.warn(warning + "Stored bytes sent: " + oldCurrentBytesSent + ", new bytes sent: " + newCurrentBytesSent + "."); + userStats.setNetBytesSent(oldNetBytesSent + oldCurrentBytesSent); + } + + userStats.setCurrentBytesReceived(newCurrentBytesReceived); + if (oldCurrentBytesReceived > newCurrentBytesReceived) { + s_logger.warn(warning + "Stored bytes received: " + oldCurrentBytesReceived + ", new bytes received: " + newCurrentBytesReceived + "."); + userStats.setNetBytesReceived(oldNetBytesReceived + oldCurrentBytesReceived); + } + + return _userStatsDao.update(userStats.getId(), userStats); + } + + /* + * Creates a new stats entry for the specified parameters, if one doesn't already exist. + */ + private boolean createStatsEntry(long accountId, long zoneId, long networkId, String publicIp, long hostId) { + HostVO host = _hostDao.findById(hostId); + UserStatisticsVO userStats = _userStatsDao.findBy(accountId, zoneId, networkId, publicIp, hostId, host.getType().toString()); + if (userStats == null) { + return (_userStatsDao.persist(new UserStatisticsVO(accountId, zoneId, publicIp, hostId, host.getType().toString(), networkId)) != null); + } else { + return true; + } + } + + /* + * Updates an existing stats entry with new data from the specified usage answer. + */ + private boolean updateStatsEntry(long accountId, long zoneId, long networkId, String publicIp, long hostId, ExternalNetworkResourceUsageAnswer answer) { + AccountVO account = _accountDao.findById(accountId); + DataCenterVO zone = _dcDao.findById(zoneId); + NetworkVO network = _networkDao.findById(networkId); + HostVO host = _hostDao.findById(hostId); + String statsEntryIdentifier = "account " + account.getAccountName() + ", zone " + zone.getName() + ", network ID " + networkId + ", host ID " + host.getName(); + + long newCurrentBytesSent = 0; + long newCurrentBytesReceived = 0; + + if (publicIp != null) { + long[] bytesSentAndReceived = null; + statsEntryIdentifier += ", public IP: " + publicIp; + + if (host.getType().equals(Host.Type.ExternalLoadBalancer) && externalLoadBalancerIsInline(host)) { + // Look up stats for the guest IP address that's mapped to the public IP address + InlineLoadBalancerNicMapVO mapping = _inlineLoadBalancerNicMapDao.findByPublicIpAddress(publicIp); + + if (mapping != null) { + NicVO nic = _nicDao.findById(mapping.getNicId()); + String loadBalancingIpAddress = nic.getIp4Address(); + bytesSentAndReceived = answer.ipBytes.get(loadBalancingIpAddress); + + if (bytesSentAndReceived != null) { + bytesSentAndReceived[0] = 0; + } + } + } else { + bytesSentAndReceived = answer.ipBytes.get(publicIp); + } + + if (bytesSentAndReceived == null) { + s_logger.debug("Didn't get an external network usage answer for public IP " + publicIp); + } else { + newCurrentBytesSent += bytesSentAndReceived[0]; + newCurrentBytesReceived += bytesSentAndReceived[1]; + } + } else { + URI broadcastURI = network.getBroadcastUri(); + if (broadcastURI == null) { + s_logger.debug("Not updating stats for guest network with ID " + network.getId() + " because the network is not implemented."); + return true; + } else { + long vlanTag = Integer.parseInt(broadcastURI.getHost()); + long[] bytesSentAndReceived = answer.guestVlanBytes.get(String.valueOf(vlanTag)); + + if (bytesSentAndReceived == null) { + s_logger.warn("Didn't get an external network usage answer for guest VLAN " + vlanTag); + } else { + newCurrentBytesSent += bytesSentAndReceived[0]; + newCurrentBytesReceived += bytesSentAndReceived[1]; + } + } + } + + UserStatisticsVO userStats; + try { + userStats = _userStatsDao.lock(accountId, zoneId, networkId, publicIp, hostId, host.getType().toString()); + } catch (Exception e) { + s_logger.warn("Unable to find user stats entry for " + statsEntryIdentifier); + return false; + } + + if (updateBytes(userStats, newCurrentBytesSent, newCurrentBytesReceived)) { + s_logger.debug("Successfully updated stats for " + statsEntryIdentifier); + return true; + } else { + s_logger.debug("Failed to update stats for " + statsEntryIdentifier); + return false; + } + } + + private boolean createOrUpdateStatsEntry(boolean create, long accountId, long zoneId, long networkId, String publicIp, long hostId, ExternalNetworkResourceUsageAnswer answer) { + if (create) { + return createStatsEntry(accountId, zoneId, networkId, publicIp, hostId); + } else { + return updateStatsEntry(accountId, zoneId, networkId, publicIp, hostId, answer); + } + } + + /* + * Creates/updates all necessary stats entries for an account and zone. + * Stats entries are created for source NAT IP addresses, static NAT rules, port forwarding rules, and load balancing rules + */ + private boolean manageStatsEntries(boolean create, long accountId, long zoneId, Network network, + HostVO externalFirewall, ExternalNetworkResourceUsageAnswer firewallAnswer, + HostVO externalLoadBalancer, ExternalNetworkResourceUsageAnswer lbAnswer) { + String accountErrorMsg = "Failed to update external network stats entry. Details: account ID = " + accountId; + Transaction txn = Transaction.open(Transaction.CLOUD_DB); + try { + txn.start(); + String networkErrorMsg = accountErrorMsg + ", network ID = " + network.getId(); + + boolean sharedSourceNat = false; + Map sourceNatCapabilities = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.SourceNat); + if (sourceNatCapabilities != null) { + String supportedSourceNatTypes = sourceNatCapabilities.get(Capability.SupportedSourceNatTypes).toLowerCase(); + if (supportedSourceNatTypes.contains("zone")) { + sharedSourceNat = true; + } + } + + if (!sharedSourceNat) { + // Manage the entry for this network's source NAT IP address + List sourceNatIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), true); + if (sourceNatIps.size() == 1) { + String publicIp = sourceNatIps.get(0).getAddress().addr(); + if (!createOrUpdateStatsEntry(create, accountId, zoneId, network.getId(), publicIp, externalFirewall.getId(), firewallAnswer)) { + throw new ExecutionException(networkErrorMsg + ", source NAT IP = " + publicIp); + } + } + + // Manage one entry for each static NAT rule in this network + List staticNatIps = _ipAddressDao.listStaticNatPublicIps(network.getId()); + for (IPAddressVO staticNatIp : staticNatIps) { + String publicIp = staticNatIp.getAddress().addr(); + if (!createOrUpdateStatsEntry(create, accountId, zoneId, network.getId(), publicIp, externalFirewall.getId(), firewallAnswer)) { + throw new ExecutionException(networkErrorMsg + ", static NAT rule public IP = " + publicIp); + } + } + + // Manage one entry for each port forwarding rule in this network + List portForwardingRules = _portForwardingRulesDao.listByNetwork(network.getId()); + for (PortForwardingRuleVO portForwardingRule : portForwardingRules) { + String publicIp = _networkMgr.getIp(portForwardingRule.getSourceIpAddressId()).getAddress().addr(); + if (!createOrUpdateStatsEntry(create, accountId, zoneId, network.getId(), publicIp, externalFirewall.getId(), firewallAnswer)) { + throw new ExecutionException(networkErrorMsg + ", port forwarding rule public IP = " + publicIp); + } + } + } else { + // Manage the account-wide entry for the external firewall + if (!createOrUpdateStatsEntry(create, accountId, zoneId, network.getId(), null, externalFirewall.getId(), firewallAnswer)) { + throw new ExecutionException(networkErrorMsg); + } + } + + // If an external load balancer is added, manage one entry for each load balancing rule in this network + if (externalLoadBalancer != null && lbAnswer != null) { + List loadBalancers = _loadBalancerDao.listByNetworkId(network.getId()); + for (LoadBalancerVO loadBalancer : loadBalancers) { + String publicIp = _networkMgr.getIp(loadBalancer.getSourceIpAddressId()).getAddress().addr(); + if (!createOrUpdateStatsEntry(create, accountId, zoneId, network.getId(), publicIp, externalLoadBalancer.getId(), lbAnswer)) { + throw new ExecutionException(networkErrorMsg + ", load balancing rule public IP = " + publicIp); + } + } + } + return txn.commit(); + } catch (Exception e) { + s_logger.warn("Exception: ", e); + txn.rollback(); + return false; + } finally { + txn.close(); + } + } + } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, + Map details, List hostTags) { + if (!(startup[0] instanceof StartupExternalLoadBalancerCommand)) { + return null; + } + host.setType(Host.Type.ExternalLoadBalancer); + return host; + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + // TODO Auto-generated method stub + return null; + } +} diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceVO.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceVO.java index e8c8f123155..1bf9cdb9d19 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceVO.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceVO.java @@ -18,6 +18,8 @@ package com.cloud.network; +import java.util.UUID; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; @@ -28,7 +30,7 @@ import javax.persistence.Id; import javax.persistence.Table; /** - * ExternalLoadBalancerDeviceVO contains information of a external load balancer devices (F5/Netscaler VPX,MPX,SDX) added into a deployment + * ExternalLoadBalancerDeviceVO contains information on external load balancer devices (F5/Netscaler VPX,MPX,SDX) added into a deployment */ @Entity @@ -40,6 +42,9 @@ public class ExternalLoadBalancerDeviceVO { @Column(name = "id") private long id; + @Column(name="uuid") + private String uuid; + @Column(name = "host_id") private long hostId; @@ -60,29 +65,29 @@ public class ExternalLoadBalancerDeviceVO { @Enumerated(value=EnumType.STRING) private LBDeviceAllocationState allocationState; - @Column(name="managed") - boolean managedDevice; + @Column(name="is_managed") + private boolean isManagedDevice; + @Column(name="is_dedicated") + private boolean isDedicatedDevice; + @Column(name = "parent_host_id") private long parentHostId; @Column(name = "capacity") private long capacity; + //keeping it enum for future possible states Maintenance, Shutdown public enum LBDeviceState { Enabled, Disabled } public enum LBDeviceAllocationState { - Free, // In this state no networks are using this device for load balancing - InSharedUse, // In this state one or more networks will be using this device for load balancing - InDedicatedUse // In this state this device is dedicated for a single network - } - - public enum LBDeviceManagedType { - CloudManaged, // Cloudstack managed load balancer (e.g. VPX instances on SDX for now, in future releases load balancer provisioned from template) - ExternalManaged // Externally managed + Free, // In this state no networks are using this device for load balancing + Shared, // In this state one or more networks will be using this device for load balancing + Dedicated, // In this state this device is dedicated for a single network + Provider // This state is set only for device that can dynamically provision LB appliances } public ExternalLoadBalancerDeviceVO(long hostId, long physicalNetworkId, String provider_name, String device_name) { @@ -92,22 +97,22 @@ public class ExternalLoadBalancerDeviceVO { this.hostId = hostId; this.state = LBDeviceState.Disabled; this.allocationState = LBDeviceAllocationState.Free; - this.managedDevice = false; + this.isManagedDevice = false; + this.uuid = UUID.randomUUID().toString(); + + if (device_name.equalsIgnoreCase(ExternalNetworkDeviceManager.NetworkDevice.NetscalerSDXLoadBalancer.getName())) { + this.allocationState = LBDeviceAllocationState.Provider; + } } public ExternalLoadBalancerDeviceVO(long hostId, long physicalNetworkId, String provider_name, String device_name, boolean managed, long parentHostId) { this(hostId, physicalNetworkId, provider_name, device_name); - this.managedDevice = managed; + this.isManagedDevice = managed; this.parentHostId = parentHostId; } - - public ExternalLoadBalancerDeviceVO(long hostId, long physicalNetworkId, String provider_name, String device_name, long capacity) { - this(hostId, physicalNetworkId, provider_name, device_name); - this.capacity = capacity; - } public ExternalLoadBalancerDeviceVO() { - + this.uuid = UUID.randomUUID().toString(); } public long getId() { @@ -161,4 +166,28 @@ public class ExternalLoadBalancerDeviceVO { public void setAllocationState(LBDeviceAllocationState allocationState) { this.allocationState = allocationState; } + + public boolean getIsManagedDevice() { + return isManagedDevice; + } + + public void setIsManagedDevice(boolean managed) { + this.isManagedDevice = managed; + } + + public boolean getIsDedicatedDevice() { + return isDedicatedDevice; + } + + public void setIsDedicatedDevice(boolean isDedicated) { + isDedicatedDevice = isDedicated; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } } diff --git a/server/src/com/cloud/network/ExternalNetworkDeviceManager.java b/server/src/com/cloud/network/ExternalNetworkDeviceManager.java index 51d24ab18ac..c8665e1dc77 100644 --- a/server/src/com/cloud/network/ExternalNetworkDeviceManager.java +++ b/server/src/com/cloud/network/ExternalNetworkDeviceManager.java @@ -21,22 +21,10 @@ package com.cloud.network; import java.util.ArrayList; import java.util.List; -import com.cloud.api.commands.AddExternalFirewallCmd; -import com.cloud.api.commands.AddExternalLoadBalancerCmd; import com.cloud.api.commands.AddNetworkDeviceCmd; -import com.cloud.api.commands.DeleteExternalFirewallCmd; -import com.cloud.api.commands.DeleteExternalLoadBalancerCmd; import com.cloud.api.commands.DeleteNetworkDeviceCmd; -import com.cloud.api.commands.ListExternalFirewallsCmd; -import com.cloud.api.commands.ListExternalLoadBalancersCmd; import com.cloud.api.commands.ListNetworkDeviceCmd; -import com.cloud.exception.InsufficientAddressCapacityException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.ResourceUnavailableException; import com.cloud.host.Host; -import com.cloud.network.rules.FirewallRule; -import com.cloud.server.api.response.ExternalFirewallResponse; -import com.cloud.server.api.response.ExternalLoadBalancerResponse; import com.cloud.server.api.response.NetworkDeviceResponse; import com.cloud.utils.component.Manager; @@ -79,20 +67,6 @@ public interface ExternalNetworkDeviceManager extends Manager { } } - public static class LoadBalancerCapacityType { - private String _capacityType; - public static final LoadBalancerCapacityType Throughput = new LoadBalancerCapacityType("Throughput"); - public static final LoadBalancerCapacityType publicIPOwned = new LoadBalancerCapacityType("publicIPOwned"); - - public LoadBalancerCapacityType(String capacityType) { - _capacityType = capacityType; - } - - public String getCapacityType() { - return _capacityType; - } - } - public Host addNetworkDevice(AddNetworkDeviceCmd cmd); public NetworkDeviceResponse getApiResponse(Host device); @@ -101,43 +75,4 @@ public interface ExternalNetworkDeviceManager extends Manager { public boolean deleteNetworkDevice(DeleteNetworkDeviceCmd cmd); - // External Firewall methods - - public Host addExternalFirewall(AddExternalFirewallCmd cmd); - - public boolean deleteExternalFirewall(DeleteExternalFirewallCmd cmd); - - public List listExternalFirewalls(ListExternalFirewallsCmd cmd); - - public ExternalFirewallResponse createExternalFirewallResponse(Host externalFirewall); - - public boolean manageGuestNetworkWithExternalFirewall(boolean add, Network network) throws ResourceUnavailableException, InsufficientCapacityException; - - public boolean applyFirewallRules(Network network, List rules) throws ResourceUnavailableException; - - public boolean applyIps(Network network, List ipAddresses) throws ResourceUnavailableException; - - public boolean manageRemoteAccessVpn(boolean create, Network network, RemoteAccessVpn vpn) throws ResourceUnavailableException; - - public boolean manageRemoteAccessVpnUsers(Network network, RemoteAccessVpn vpn, List users) throws ResourceUnavailableException; - - // External Load balancer methods - - public Host addExternalLoadBalancer(AddExternalLoadBalancerCmd cmd); - - public boolean deleteExternalLoadBalancer(DeleteExternalLoadBalancerCmd cmd); - - public List listExternalLoadBalancers(ListExternalLoadBalancersCmd cmd); - - public ExternalLoadBalancerResponse createExternalLoadBalancerResponse(Host externalLoadBalancer); - - public boolean manageGuestNetworkWithExternalLoadBalancer(boolean add, Network guestConfig) throws ResourceUnavailableException, InsufficientCapacityException; - - public boolean applyLoadBalancerRules(Network network, List rules) throws ResourceUnavailableException; - - // General methods - - public int getVlanOffset(long physicalNetworkId, int vlanTag); - - public int getGloballyConfiguredCidrSize(); } diff --git a/server/src/com/cloud/network/ExternalNetworkDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalNetworkDeviceManagerImpl.java index 20c4b47cb50..9ca1e53157d 100644 --- a/server/src/com/cloud/network/ExternalNetworkDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalNetworkDeviceManagerImpl.java @@ -1,6 +1,6 @@ /** * * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved - * +* * * This software is licensed under the GNU General Public License v3 or later. * @@ -19,15 +19,12 @@ package com.cloud.network; -import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; import javax.ejb.Local; import javax.naming.ConfigurationException; @@ -35,59 +32,23 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer; -import com.cloud.agent.api.ExternalNetworkResourceUsageCommand; -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.routing.RemoteAccessVpnCfgCommand; -import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; -import com.cloud.agent.api.routing.SetStaticNatRulesCommand; -import com.cloud.agent.api.routing.VpnUsersCfgCommand; -import com.cloud.agent.api.to.IpAddressTO; -import com.cloud.agent.api.to.LoadBalancerTO; -import com.cloud.agent.api.to.PortForwardingRuleTO; -import com.cloud.agent.api.to.StaticNatRuleTO; import com.cloud.api.ApiConstants; -import com.cloud.api.commands.AddExternalFirewallCmd; -import com.cloud.api.commands.AddExternalLoadBalancerCmd; +import com.cloud.api.PlugService; import com.cloud.api.commands.AddNetworkDeviceCmd; -import com.cloud.api.commands.DeleteExternalFirewallCmd; -import com.cloud.api.commands.DeleteExternalLoadBalancerCmd; import com.cloud.api.commands.DeleteNetworkDeviceCmd; -import com.cloud.api.commands.ListExternalFirewallsCmd; -import com.cloud.api.commands.ListExternalLoadBalancersCmd; import com.cloud.api.commands.ListNetworkDeviceCmd; import com.cloud.baremetal.ExternalDhcpManager; import com.cloud.baremetal.PxeServerManager; -import com.cloud.baremetal.PxeServerManager.PxeServerType; import com.cloud.baremetal.PxeServerProfile; -import com.cloud.configuration.Config; +import com.cloud.baremetal.PxeServerManager.PxeServerType; import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.dc.DataCenter; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.Vlan; -import com.cloud.dc.VlanVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.VlanDao; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InsufficientNetworkCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.host.DetailVO; import com.cloud.host.Host; -import com.cloud.host.Host.Type; import com.cloud.host.HostVO; +import com.cloud.host.Host.Type; import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDetailsDao; -import com.cloud.network.ExternalLoadBalancerDeviceVO.LBDeviceAllocationState; -import com.cloud.network.ExternalLoadBalancerDeviceVO.LBDeviceState; -import com.cloud.network.Network.Capability; -import com.cloud.network.Network.Provider; -import com.cloud.network.Network.Service; -import com.cloud.network.Networks.TrafficType; import com.cloud.network.dao.ExternalFirewallDeviceDao; import com.cloud.network.dao.ExternalLoadBalancerDeviceDao; import com.cloud.network.dao.IPAddressDao; @@ -99,61 +60,29 @@ import com.cloud.network.dao.NetworkExternalLoadBalancerDao; import com.cloud.network.dao.NetworkServiceMapDao; import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; -import com.cloud.network.dao.PhysicalNetworkServiceProviderVO; import com.cloud.network.dao.VpnUserDao; -import com.cloud.network.lb.LoadBalancingRule; -import com.cloud.network.lb.LoadBalancingRule.LbDestination; +import com.cloud.network.element.F5ExternalLoadBalancerElementService; +import com.cloud.network.element.JuniperSRXFirewallElementService; +import com.cloud.network.element.NetscalerLoadBalancerElementService; import com.cloud.network.resource.F5BigIpResource; import com.cloud.network.resource.JuniperSrxResource; import com.cloud.network.resource.NetscalerResource; -import com.cloud.network.rules.FirewallRule; -import com.cloud.network.rules.FirewallRule.Purpose; -import com.cloud.network.rules.FirewallRuleVO; -import com.cloud.network.rules.PortForwardingRule; -import com.cloud.network.rules.PortForwardingRuleVO; -import com.cloud.network.rules.StaticNatRule; -import com.cloud.network.rules.StaticNatRuleImpl; import com.cloud.network.rules.dao.PortForwardingRulesDao; -import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; -import com.cloud.resource.ResourceManager; import com.cloud.resource.ServerResource; -import com.cloud.server.api.response.ExternalFirewallResponse; -import com.cloud.server.api.response.ExternalLoadBalancerResponse; import com.cloud.server.api.response.NetworkDeviceResponse; import com.cloud.server.api.response.NwDeviceDhcpResponse; import com.cloud.server.api.response.PxePingResponse; -import com.cloud.user.Account; import com.cloud.user.AccountManager; -import com.cloud.user.AccountVO; -import com.cloud.user.User; -import com.cloud.user.UserContext; -import com.cloud.user.UserStatisticsVO; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserStatisticsDao; -import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.Inject; -import com.cloud.utils.concurrency.NamedThreadFactory; -import com.cloud.utils.db.GlobalLock; -import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.exception.ExecutionException; -import com.cloud.utils.net.NetUtils; -import com.cloud.utils.net.UrlUtil; -import com.cloud.vm.DomainRouterVO; -import com.cloud.vm.Nic.ReservationStrategy; -import com.cloud.vm.Nic.State; -import com.cloud.vm.NicVO; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.NicDao; @Local(value = {ExternalNetworkDeviceManager.class}) public class ExternalNetworkDeviceManagerImpl implements ExternalNetworkDeviceManager { - public enum ExternalNetworkResourceName { - JuniperSrx, - F5BigIp, - NetscalerMPX; - } @Inject ExternalDhcpManager _dhcpMgr; @Inject PxeServerManager _pxeMgr; @@ -182,30 +111,25 @@ public class ExternalNetworkDeviceManagerImpl implements ExternalNetworkDeviceMa @Inject ExternalFirewallDeviceDao _externalFirewallDeviceDao; @Inject NetworkExternalLoadBalancerDao _networkExternalLBDao; @Inject NetworkExternalFirewallDao _networkExternalFirewallDao; - @Inject ResourceManager _resourceMgr; - @Inject NetworkServiceMapDao _ntwkSrvcProviderDao; + + @PlugService NetscalerLoadBalancerElementService _netsclarLbService; + @PlugService F5ExternalLoadBalancerElementService _f5LbElementService; + @PlugService JuniperSRXFirewallElementService _srxElementService; ScheduledExecutorService _executor; int _externalNetworkStatsInterval; - + private static final org.apache.log4j.Logger s_logger = Logger.getLogger(ExternalNetworkDeviceManagerImpl.class); protected String _name; - + @Override public boolean configure(String name, Map params) throws ConfigurationException { _name = name; - _externalNetworkStatsInterval = NumbersUtil.parseInt(_configDao.getValue(Config.RouterStatsInterval.key()), 300); - if (_externalNetworkStatsInterval > 0){ - _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("ExternalNetworkMonitor")); - } return true; } - + @Override public boolean start() { - if (_externalNetworkStatsInterval > 0){ - _executor.scheduleAtFixedRate(new ExternalNetworkUsageTask(), _externalNetworkStatsInterval, _externalNetworkStatsInterval, TimeUnit.SECONDS); - } return true; } @@ -218,14 +142,14 @@ public class ExternalNetworkDeviceManagerImpl implements ExternalNetworkDeviceMa public String getName() { return _name; } - + @Override public Host addNetworkDevice(AddNetworkDeviceCmd cmd) { Map paramList = cmd.getParamList(); if (paramList == null) { throw new CloudRuntimeException("Parameter list is null"); } - + Collection paramsCollection = paramList.values(); HashMap params = (HashMap) (paramsCollection.toArray())[0]; if (cmd.getDeviceType().equalsIgnoreCase(NetworkDevice.ExternalDhcp.getName())) { @@ -253,16 +177,32 @@ public class ExternalNetworkDeviceManagerImpl implements ExternalNetworkDeviceMa pingCifsUsername, pingCifsPassword); return _pxeMgr.addPxeServer(profile); } else if (cmd.getDeviceType().equalsIgnoreCase(NetworkDevice.JuniperSRXFirewall.getName())) { - Long zoneId = Long.parseLong((String) params.get(ApiConstants.ZONE_ID)); Long physicalNetworkId = (params.get(ApiConstants.PHYSICAL_NETWORK_ID)==null)?Long.parseLong((String)params.get(ApiConstants.PHYSICAL_NETWORK_ID)):null; - return addExternalFirewall(zoneId, physicalNetworkId, NetworkDevice.JuniperSRXFirewall.getName(), cmd.getParamList()); + String url = (String) params.get(ApiConstants.URL); + String username = (String) params.get(ApiConstants.USERNAME); + String password = (String) params.get(ApiConstants.PASSWORD); + ExternalFirewallDeviceManager fwDeviceManager = (ExternalFirewallDeviceManager) _srxElementService; + return fwDeviceManager.addExternalFirewall(physicalNetworkId, url, username, password, NetworkDevice.JuniperSRXFirewall.getName(),new JuniperSrxResource()); } else if (cmd.getDeviceType().equalsIgnoreCase(NetworkDevice.NetscalerMPXLoadBalancer.getName()) || cmd.getDeviceType().equalsIgnoreCase(NetworkDevice.NetscalerVPXLoadBalancer.getName()) || - cmd.getDeviceType().equalsIgnoreCase(NetworkDevice.NetscalerSDXLoadBalancer.getName()) || - cmd.getDeviceType().equalsIgnoreCase(NetworkDevice.F5BigIpLoadBalancer.getName())) { - Long zoneId = Long.parseLong((String) params.get(ApiConstants.ZONE_ID)); + cmd.getDeviceType().equalsIgnoreCase(NetworkDevice.NetscalerSDXLoadBalancer.getName())) { Long physicalNetworkId = (params.get(ApiConstants.PHYSICAL_NETWORK_ID)==null)?Long.parseLong((String)params.get(ApiConstants.PHYSICAL_NETWORK_ID)):null; - return addExternalLoadBalancer(zoneId, physicalNetworkId, cmd.getDeviceType(), cmd.getParamList()); + String url = (String) params.get(ApiConstants.URL); + String username = (String) params.get(ApiConstants.USERNAME); + String password = (String) params.get(ApiConstants.PASSWORD); + ExternalLoadBalancerDeviceManager lbDeviceMgr = (ExternalLoadBalancerDeviceManager) _netsclarLbService; + ExternalLoadBalancerDeviceVO lbDeviceVO = lbDeviceMgr.addExternalLoadBalancer(physicalNetworkId, + url, username, password, cmd.getDeviceType(), (ServerResource) new NetscalerResource()); + return _hostDao.findById(lbDeviceVO.getHostId()); + } else if (cmd.getDeviceType().equalsIgnoreCase(NetworkDevice.F5BigIpLoadBalancer.getName())) { + Long physicalNetworkId = (params.get(ApiConstants.PHYSICAL_NETWORK_ID)==null)?Long.parseLong((String)params.get(ApiConstants.PHYSICAL_NETWORK_ID)):null; + String url = (String) params.get(ApiConstants.URL); + String username = (String) params.get(ApiConstants.USERNAME); + String password = (String) params.get(ApiConstants.PASSWORD); + ExternalLoadBalancerDeviceManager lbDeviceMgr = (ExternalLoadBalancerDeviceManager) _f5LbElementService; + ExternalLoadBalancerDeviceVO lbDeviceVO = lbDeviceMgr.addExternalLoadBalancer(physicalNetworkId, url, username, password, + cmd.getDeviceType(), (ServerResource) new F5BigIpResource()); + return _hostDao.findById(lbDeviceVO.getHostId()); } else { throw new CloudRuntimeException("Unsupported network device type:" + cmd.getDeviceType()); } @@ -296,13 +236,14 @@ public class ExternalNetworkDeviceManagerImpl implements ExternalNetworkDeviceMa throw new CloudRuntimeException("Unsupported PXE server type:" + pxeType); } } else if (host.getType() == Host.Type.ExternalLoadBalancer) { - response = createExternalLoadBalancerResponse(host); + ExternalLoadBalancerDeviceManager lbDeviceMgr = (ExternalLoadBalancerDeviceManager) _f5LbElementService; + response = _f5LbElementService.createExternalLoadBalancerResponse(host); } else if (host.getType() == Host.Type.ExternalFirewall) { - response = createExternalFirewallResponse(host); + response = _srxElementService.createExternalFirewallResponse(host); } else { throw new CloudRuntimeException("Unsupported network device type:" + host.getType()); } - + response.setId(device.getId()); return response; } @@ -319,19 +260,19 @@ public class ExternalNetworkDeviceManagerImpl implements ExternalNetworkDeviceMa // } else { // List devs = _hostDao.listBy(type, zoneId); // res.addAll(devs); -// } -// -// return res; + // } + + // return res; return null; } - + @Override public List listNetworkDevice(ListNetworkDeviceCmd cmd) { Map paramList = cmd.getParamList(); if (paramList == null) { throw new CloudRuntimeException("Parameter list is null"); } - + List res; Collection paramsCollection = paramList.values(); HashMap params = (HashMap) (paramsCollection.toArray())[0]; @@ -349,11 +290,13 @@ public class ExternalNetworkDeviceManagerImpl implements ExternalNetworkDeviceMa cmd.getDeviceType().equalsIgnoreCase(NetworkDevice.F5BigIpLoadBalancer.getName())) { Long zoneId = Long.parseLong((String) params.get(ApiConstants.ZONE_ID)); Long physicalNetworkId = (params.get(ApiConstants.PHYSICAL_NETWORK_ID)==null)?Long.parseLong((String)params.get(ApiConstants.PHYSICAL_NETWORK_ID)):null; - return listExternalLoadBalancers(zoneId, physicalNetworkId, cmd.getDeviceType()); + ExternalLoadBalancerDeviceManager lbDeviceMgr = (ExternalLoadBalancerDeviceManager) _f5LbElementService; + return lbDeviceMgr.listExternalLoadBalancers(physicalNetworkId, cmd.getDeviceType()); } else if (NetworkDevice.JuniperSRXFirewall.getName().equalsIgnoreCase(cmd.getDeviceType())) { Long zoneId = Long.parseLong((String) params.get(ApiConstants.ZONE_ID)); Long physicalNetworkId = (params.get(ApiConstants.PHYSICAL_NETWORK_ID)==null)?Long.parseLong((String)params.get(ApiConstants.PHYSICAL_NETWORK_ID)):null; - return listExternalFirewalls(zoneId, physicalNetworkId, NetworkDevice.JuniperSRXFirewall.getName()); + ExternalFirewallDeviceManager fwDeviceManager = (ExternalFirewallDeviceManager) _srxElementService; + return fwDeviceManager.listExternalFirewalls(physicalNetworkId, NetworkDevice.JuniperSRXFirewall.getName()); } else if (cmd.getDeviceType() == null){ Long zoneId = Long.parseLong((String) params.get(ApiConstants.ZONE_ID)); Long podId = Long.parseLong((String)params.get(ApiConstants.POD_ID)); @@ -371,1434 +314,20 @@ public class ExternalNetworkDeviceManagerImpl implements ExternalNetworkDeviceMa } else { throw new CloudRuntimeException("Unknown network device type:" + cmd.getDeviceType()); } - + return res; } @Override public boolean deleteNetworkDevice(DeleteNetworkDeviceCmd cmd) { - HostVO device = _hostDao.findById(cmd.getId()); - if (device.getType() == Type.ExternalLoadBalancer) { - return deleteExternalLoadBalancer(cmd.getId()); - } else if (device.getType() == Type.ExternalLoadBalancer) { - return deleteExternalFirewall(cmd.getId()); - } - return true; - } - - public String getExternalNetworkResourceGuid(long zoneId, ExternalNetworkResourceName name, String ip) { - return zoneId + "-" + name + "-" + ip; - } - - protected HostVO getExternalLoadBalancerForNetwork(Network network) { - NetworkExternalLoadBalancerVO lbDeviceForNetwork = _networkExternalLBDao.findByNetworkId(network.getId()); - if (lbDeviceForNetwork != null) { - long lbDeviceId = lbDeviceForNetwork.getExternalLBDeviceId(); - ExternalLoadBalancerDeviceVO lbDeviceVo = _externalLoadBalancerDeviceDao.findById(lbDeviceId); - assert(lbDeviceVo != null); - _hostDao.findById(lbDeviceVo.getHostId()); - } - return null; - } - - protected HostVO getExternalFirewallForNetwork(Network network) { - NetworkExternalFirewallVO fwDeviceForNetwork = _networkExternalFirewallDao.findByNetworkId(network.getId()); - if (fwDeviceForNetwork != null) { - long fwDeviceId = fwDeviceForNetwork.getExternalFirewallDeviceId(); - ExternalFirewallDeviceVO fwDeviceVO = _externalFirewallDeviceDao.findById(fwDeviceId); - assert(fwDeviceVO != null); - _hostDao.findById(fwDeviceVO.getHostId()); - } - return null; - } - - protected void setExternalLoadBalancerForNetwork(Network network, long externalLBDeviceID) { - NetworkExternalLoadBalancerVO lbDeviceForNetwork = new NetworkExternalLoadBalancerVO(network.getId(), externalLBDeviceID); - _networkExternalLBDao.persist(lbDeviceForNetwork); - } - - protected void setExternalFirewallForNetwork(Network network, long externalFWDeviceID) { - NetworkExternalFirewallVO fwDeviceForNetwork = new NetworkExternalFirewallVO(network.getId(), externalFWDeviceID); - _networkExternalFirewallDao.persist(fwDeviceForNetwork); - } - - protected long findSuitableLoadBalancerForNetwork(Network network, boolean dedicatedLb) throws InsufficientCapacityException { - long physicalNetworkId = network.getPhysicalNetworkId(); - List lbDevices =null; - String provider = _ntwkSrvcProviderDao.getProviderForServiceInNetwork(network.getId(), Service.Lb); - assert(provider != null); - - if (dedicatedLb) { - lbDevices = _externalLoadBalancerDeviceDao.listByDeviceAllocationState(physicalNetworkId, provider, LBDeviceAllocationState.Free); - if (lbDevices != null && !lbDevices.isEmpty()) { - for (ExternalLoadBalancerDeviceVO lbdevice : lbDevices) { - if (lbdevice.getState() == LBDeviceState.Enabled) { - return lbdevice.getId(); //return first device that is free and fully configured - } - } - } - } else { - // get the LB devices that are already allocated for shared use - lbDevices = _externalLoadBalancerDeviceDao.listByDeviceAllocationState(physicalNetworkId, provider, LBDeviceAllocationState.InSharedUse); - - if (lbDevices != null) { - // loop through the LB device in the physical network and pick the first-fit - for (ExternalLoadBalancerDeviceVO lbdevice: lbDevices) { - - // skip if device is not enabled - if (lbdevice.getState() != LBDeviceState.Enabled) { - continue; - } - - // get max number of guest networks that can be mapped to this device - long fullCapacity = lbdevice.getCapacity(); - assert (fullCapacity != 0) : "How did the capacity of device ended up as zero?"; - - // get the list of guest networks that are mapped to this load balancer - List mappedNetworks = _networkExternalLBDao.listByLBDeviceId(lbdevice.getId()); - - long usedCapacity = ((mappedNetworks == null) || (mappedNetworks.isEmpty()))? 0 : mappedNetworks.size(); - if ((fullCapacity - usedCapacity) > 0) { - return lbdevice.getId(); - } - } - } - - // if we are here then there are no existing LB devices in shared use or the devices in shared use has no free capacity - // so allocate a new one from the pool of free LB devices - lbDevices = _externalLoadBalancerDeviceDao.listByDeviceAllocationState(physicalNetworkId, provider, LBDeviceAllocationState.Free); - if (lbDevices != null && !lbDevices.isEmpty()) { - for (ExternalLoadBalancerDeviceVO lbdevice : lbDevices) { - if (lbdevice.getState() == LBDeviceState.Enabled) { - return lbdevice.getId(); //return first device that is free and fully configured - } - } - } - } - - // there are no LB device or there is no free capacity on the devices in the physical network - // FIXME: check if new device from SDX can be provisioned - - throw new InsufficientNetworkCapacityException("Unable to find a load balancing provider with sufficient capcity " + - " to implement the network", Network.class, network.getId()); - } - - protected long findSuitableFirewallDeviceForNetwork(Network network) throws InsufficientCapacityException { - long physicalNetworkId = network.getPhysicalNetworkId(); - List fwDevices = _externalFirewallDeviceDao.listByPhysicalNetwork(physicalNetworkId); - - // loop through the firewall device in the physical network and pick the first-fit - for (ExternalFirewallDeviceVO fwDevice: fwDevices) { - // max number of guest networks that can be mapped to this device - long fullCapacity = fwDevice.getCapacity(); - - // get the list of guest networks that are mapped to this load balancer - List mappedNetworks = _networkExternalFirewallDao.listByFirewallDeviceId(fwDevice.getId()); - - long usedCapacity = (mappedNetworks == null) ? 0 : mappedNetworks.size(); - if ((fullCapacity - usedCapacity) > 0) { - return fwDevice.getId(); - } - } - throw new InsufficientNetworkCapacityException("Unable to find a firewall provider with sufficient capcity " + - " to implement the network", Network.class, network.getId()); - } - - @Override - @Deprecated // should use more generic addNetworkDevice command to add external load balancer - public Host addExternalLoadBalancer(AddExternalLoadBalancerCmd cmd) { - Long zoneId = cmd.getZoneId(); - // AddExternalLoadBalancerCmd support only F5 Big IP (api exists for backward compatibility) - String deviceType = NetworkDevice.F5BigIpLoadBalancer.getName(); - Map deviceParams = new HashMap(); - deviceParams.put(ApiConstants.USERNAME, cmd.getUsername()); - deviceParams.put(ApiConstants.PASSWORD, cmd.getPassword()); - deviceParams.put(ApiConstants.URL, cmd.getUrl()); - return addExternalLoadBalancer(zoneId, null, deviceType, deviceParams); - } - - public Host addExternalLoadBalancer(Long zoneId, Long physicalNetworkId, String deviceName, Map deviceParamList) { - - ServerResource resource =null; - String guid; - PhysicalNetworkVO pNetwork=null; - DataCenterVO zone =null; - NetworkDevice ntwkDevice = NetworkDevice.getNetworkDevice(deviceName); - String url=null; - String username=null; - String password=null; - - if (deviceParamList != null) { - url = (String) deviceParamList.get(ApiConstants.URL); - username = (String) deviceParamList.get(ApiConstants.USERNAME); - password = (String) deviceParamList.get(ApiConstants.PASSWORD); - } - - if (((zoneId == null) && (physicalNetworkId == null)) || (ntwkDevice == null) || (url == null) || (username == null) || (password == null) ) { - throw new InvalidParameterValueException("Atleast one of the required parameters (url, username, password," + - " zone id/physical network id) is not specified or a valid parameter."); - } - - if (physicalNetworkId != null) { - pNetwork = _physicalNetworkDao.findById(physicalNetworkId); - if (pNetwork == null) { - throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId); - } - } - - if (zoneId != null) { - zone = _dcDao.findById(zoneId); - if (zone == null) { - throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId); - } - if (pNetwork == null) { - List 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 + ". Physical network ID must be passed to select a physical network in this zone."); - } - pNetwork = physicalNetworks.get(0); - } - } - - PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), ntwkDevice.getNetworkServiceProvder()); - if ((ntwkSvcProvider == null ) || (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) - || (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Disabled)) { - throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() + - " is not added or in shutdown state in the physical network: " + physicalNetworkId + "to add this device" ); - } - - URI uri; - try { - uri = new URI(url); - } catch (Exception e) { - s_logger.debug(e); - throw new InvalidParameterValueException(e.getMessage()); - } - - String ipAddress = uri.getHost(); - - Map params = new HashMap(); - UrlUtil.parseQueryParameters(uri.getQuery(), true, params); - String publicInterface = params.get("publicinterface"); - String privateInterface = params.get("privateinterface"); - String numRetries = params.get("numretries"); - boolean inline = Boolean.parseBoolean(params.get("inline")); - - if (publicInterface == null) { - throw new InvalidParameterValueException("Please specify a public interface."); - } - - if (privateInterface == null) { - throw new InvalidParameterValueException("Please specify a private interface."); - } - - if (numRetries == null) { - numRetries = "1"; - } - - if (deviceName.equalsIgnoreCase(NetworkDevice.F5BigIpLoadBalancer.getName())) { - resource = new F5BigIpResource(); - guid = getExternalNetworkResourceGuid(zoneId, ExternalNetworkResourceName.F5BigIp, ipAddress); - } else if (Provider.Netscaler.getName().equalsIgnoreCase(ntwkDevice.getNetworkServiceProvder())) { - resource = new NetscalerResource(); - guid = getExternalNetworkResourceGuid(zoneId, ExternalNetworkResourceName.NetscalerMPX, ipAddress); - } else { - throw new CloudRuntimeException("An unsupported networt device type is added as external load balancer."); - } - - - Map hostDetails = new HashMap(); - hostDetails.put("zoneId", String.valueOf(zoneId)); - hostDetails.put("ip", ipAddress); - hostDetails.put("username", username); - hostDetails.put("password", password); - hostDetails.put("publicInterface", publicInterface); - hostDetails.put("privateInterface", privateInterface); - hostDetails.put("numRetries", numRetries); - hostDetails.put("guid", guid); - hostDetails.put("name", guid); - hostDetails.put("inline", String.valueOf(inline)); - hostDetails.put("deviceName", deviceName); - - try { - resource.configure(guid, hostDetails); - } catch (ConfigurationException e) { - throw new CloudRuntimeException(e.getMessage()); - } - - Host host = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalLoadBalancer, hostDetails); - if (host != null) { - Transaction txn = Transaction.currentTxn(); - txn.start(); - ExternalLoadBalancerDeviceVO device = new ExternalLoadBalancerDeviceVO(host.getId(), pNetwork.getId(), ntwkSvcProvider.getProviderName(), deviceName); - _externalLoadBalancerDeviceDao.persist(device); - txn.commit(); - return host; - } else { - return null; - } - } - - @Override - public boolean deleteExternalLoadBalancer(DeleteExternalLoadBalancerCmd cmd) { - return deleteExternalLoadBalancer(cmd.getId()); - } - - public boolean deleteExternalLoadBalancer(Long hostId) { - User caller = _accountMgr.getActiveUser(UserContext.current().getCallerUserId()); - HostVO externalLoadBalancer = _hostDao.findById(hostId); - if (externalLoadBalancer == null) { - throw new InvalidParameterValueException("Could not find an external load balancer with ID: " + hostId); - } - - try { - if (_resourceMgr.maintain(hostId) && _resourceMgr.deleteHost(hostId, false, false)) { - // FIXME: device maintenance , rules reprogramming - DataCenterVO zone = _dcDao.findById(externalLoadBalancer.getDataCenterId()); - return _dcDao.update(zone.getId(), zone); - } else { - return false; - } - } catch (AgentUnavailableException e) { - s_logger.debug(e); - return false; - } - } - - @Override - @Deprecated // should use more generic listNetworkDevice command - public List listExternalLoadBalancers(ListExternalLoadBalancersCmd cmd) { - List lbHosts = new ArrayList(); - lbHosts.addAll(listExternalLoadBalancers(cmd.getZoneId(), null, NetworkDevice.F5BigIpLoadBalancer.getName())); - return lbHosts; - } - - public List listExternalLoadBalancers(Long zoneId, Long physicalNetworkId, String deviceName) { - List lbHosts = new ArrayList(); - List lbHostsInZone = new ArrayList(); - NetworkDevice lbNetworkDevice = NetworkDevice.getNetworkDevice(deviceName); - PhysicalNetworkVO pNetwork=null; - - if (((zoneId == null) && (physicalNetworkId == null)) || (lbNetworkDevice == null)) { - throw new InvalidParameterValueException("Atleast one of the required parameter zone Id, physical networkId, device name is missing or invalid."); - } - - if (physicalNetworkId != null) { - pNetwork = _physicalNetworkDao.findById(physicalNetworkId); - if (pNetwork == null) { - throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId); - } - } - - if (zoneId != null) { - if (_dcDao.findById(zoneId) == null) { - throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId); - } - lbHostsInZone.addAll(_resourceMgr.listAllHostsInOneZoneByType(Host.Type.ExternalLoadBalancer, zoneId)); - } - if (physicalNetworkId == null) { - return lbHostsInZone; - } - - PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), - lbNetworkDevice.getNetworkServiceProvder()); - //if provider not configured in to physical network, then there can be no instances - if (ntwkSvcProvider == null) { - return null; - } - - List lbDevices = _externalLoadBalancerDeviceDao.listByPhysicalNetworkServiceProvider(physicalNetworkId, - ntwkSvcProvider.getProviderName()); - for (ExternalLoadBalancerDeviceVO provderInstance : lbDevices) { - lbHosts.add(_hostDao.findById(provderInstance.getHostId())); - } - return lbHosts; - } - - @Override - public ExternalLoadBalancerResponse createExternalLoadBalancerResponse(Host externalLoadBalancer) { - Map lbDetails = _detailsDao.findDetails(externalLoadBalancer.getId()); - ExternalLoadBalancerResponse response = new ExternalLoadBalancerResponse(); - response.setId(externalLoadBalancer.getId()); - response.setIpAddress(externalLoadBalancer.getPrivateIpAddress()); - response.setUsername(lbDetails.get("username")); - response.setPublicInterface(lbDetails.get("publicInterface")); - response.setPrivateInterface(lbDetails.get("privateInterface")); - response.setNumRetries(lbDetails.get("numRetries")); - return response; - } - - @Override - public boolean manageGuestNetworkWithExternalLoadBalancer(boolean add, Network guestConfig) throws ResourceUnavailableException, InsufficientCapacityException { - if (guestConfig.getTrafficType() != TrafficType.Guest) { - s_logger.trace("External load balancer can only be user for guest networks."); - return false; - } - - long zoneId = guestConfig.getDataCenterId(); - DataCenterVO zone = _dcDao.findById(zoneId); - HostVO externalLoadBalancer = null; - - if (add) { - GlobalLock deviceMapLock = GlobalLock.getInternLock("LoadBalancerAllocLock"); - Transaction txn = Transaction.currentTxn(); - try { - if (deviceMapLock.lock(120)) { - try { - NetworkOfferingVO offering = _networkOfferingDao.findById(guestConfig.getNetworkOfferingId()); - long lbDeviceId; - txn.start(); - - // find a load balancer device as per the network offering - boolean dedicatedLB = offering.getDedicatedLB(); - lbDeviceId = findSuitableLoadBalancerForNetwork(guestConfig, dedicatedLB); - - // persist the load balancer device id that will be used for this network. Once a network - // is implemented on a LB device then later on all rules will be programmed on to same device - NetworkExternalLoadBalancerVO networkLB = new NetworkExternalLoadBalancerVO(guestConfig.getId(), lbDeviceId); - _networkExternalLBDao.persist(networkLB); - - // mark device to be in use - ExternalLoadBalancerDeviceVO lbDevice = _externalLoadBalancerDeviceDao.findById(lbDeviceId); - lbDevice.setAllocationState(dedicatedLB ? LBDeviceAllocationState.InDedicatedUse : LBDeviceAllocationState.InSharedUse); - _externalLoadBalancerDeviceDao.update(lbDeviceId, lbDevice); - - // return the HostVO for the lb device - externalLoadBalancer = _hostDao.findById(lbDevice.getHostId()); - - txn.commit(); - } finally { - deviceMapLock.unlock(); - if (externalLoadBalancer == null) { - txn.rollback(); - } - } - } - } finally { - deviceMapLock.releaseRef(); - } - } else { - // find the load balancer device allocated for the network - externalLoadBalancer = getExternalLoadBalancerForNetwork(guestConfig); - assert (externalLoadBalancer != null) : "There is no device assigned to this network how did shutdown network ended up here??"; - } - - // Send a command to the external load balancer to implement or shutdown the guest network - long guestVlanTag = Long.parseLong(guestConfig.getBroadcastUri().getHost()); - String selfIp = NetUtils.long2Ip(NetUtils.ip2Long(guestConfig.getGateway()) + 1); - String guestVlanNetmask = NetUtils.cidr2Netmask(guestConfig.getCidr()); - Integer networkRate = _networkMgr.getNetworkRate(guestConfig.getId(), null); - - IpAddressTO ip = new IpAddressTO(guestConfig.getAccountId(), null, add, false, true, String.valueOf(guestVlanTag), selfIp, guestVlanNetmask, null, null, networkRate, false); - IpAddressTO[] ips = new IpAddressTO[1]; - ips[0] = ip; - IpAssocCommand cmd = new IpAssocCommand(ips); - Answer answer = _agentMgr.easySend(externalLoadBalancer.getId(), cmd); - - if (answer == null || !answer.getResult()) { - String action = add ? "implement" : "shutdown"; - String answerDetails = (answer != null) ? answer.getDetails() : "answer was null"; - String msg = "External load balancer was unable to " + action + " the guest network on the external load balancer in zone " + zone.getName() + " due to " + answerDetails; - s_logger.error(msg); - throw new ResourceUnavailableException(msg, DataCenter.class, zoneId); - } - - List reservedIpAddressesForGuestNetwork = _nicDao.listIpAddressInNetwork(guestConfig.getId()); - if (add && (!reservedIpAddressesForGuestNetwork.contains(selfIp))) { - // Insert a new NIC for this guest network to reserve the self IP - savePlaceholderNic(guestConfig, selfIp); - } - - if (!add) { - Transaction txn = Transaction.currentTxn(); - txn.start(); - - // since network is shutdown remove the network mapping to the load balancer device - NetworkExternalLoadBalancerVO networkLBDevice = _networkExternalLBDao.findByNetworkId(guestConfig.getId()); - _networkExternalLBDao.remove(networkLBDevice.getId()); - - // if this is the last network mapped to the load balancer device then set device allocation state to be free - List ntwksMapped = _networkExternalLBDao.listByLBDeviceId(networkLBDevice.getExternalLBDeviceId()); - if (ntwksMapped == null || ntwksMapped.isEmpty()) { - ExternalLoadBalancerDeviceVO lbDevice = _externalLoadBalancerDeviceDao.findById(networkLBDevice.getExternalLBDeviceId()); - lbDevice.setAllocationState(LBDeviceAllocationState.Free); - _externalLoadBalancerDeviceDao.update(lbDevice.getId(), lbDevice); - - //TODO: if device is cloud managed then take action - } - txn.commit(); - } - - Account account = _accountDao.findByIdIncludingRemoved(guestConfig.getAccountId()); - String action = add ? "implemented" : "shut down"; - s_logger.debug("External load balancer has " + action + " the guest network for account " + account.getAccountName() + "(id = " + account.getAccountId() + ") with VLAN tag " + guestVlanTag); - - return true; - } - - @Override - public boolean applyLoadBalancerRules(Network network, List rules) throws ResourceUnavailableException { - // Find the external load balancer in this zone - long zoneId = network.getDataCenterId(); - DataCenterVO zone = _dcDao.findById(zoneId); - - HostVO externalLoadBalancer = getExternalLoadBalancerForNetwork(network); - assert(externalLoadBalancer != null) : "There is no device assigned to this network how apply rules ended up here??"; - - // FIXME: remove this restriction for in-line case firewall provider need not be external firewall - boolean externalLoadBalancerIsInline = externalLoadBalancerIsInline(externalLoadBalancer); - HostVO externalFirewall = null; - if (externalLoadBalancerIsInline) { - externalFirewall = getExternalFirewallForNetwork(network); - if (externalFirewall == null) { - String msg = "External load balancer in zone " + zone.getName() + " is inline, but no external firewall in this zone."; - s_logger.error(msg); - throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId()); - } - } - - if (network.getState() == Network.State.Allocated) { - s_logger.debug("External load balancer was asked to apply LB rules for network with ID " + network.getId() + "; this network is not implemented. Skipping backend commands."); - return true; - } - - List loadBalancingRules = new ArrayList(); - - for (FirewallRule rule : rules) { - if (rule.getPurpose().equals(Purpose.LoadBalancing)) { - loadBalancingRules.add((LoadBalancingRule) rule); - } - } - - List loadBalancersToApply = new ArrayList(); - for (int i = 0; i < loadBalancingRules.size(); i++) { - LoadBalancingRule rule = loadBalancingRules.get(i); - - boolean revoked = (rule.getState().equals(FirewallRule.State.Revoke)); - String protocol = rule.getProtocol(); - String algorithm = rule.getAlgorithm(); - String srcIp = _networkMgr.getIp(rule.getSourceIpAddressId()).getAddress().addr(); - int srcPort = rule.getSourcePortStart(); - List destinations = rule.getDestinations(); - List sourceCidrs = rule.getSourceCidrList(); - - if (externalLoadBalancerIsInline) { - InlineLoadBalancerNicMapVO mapping = _inlineLoadBalancerNicMapDao.findByPublicIpAddress(srcIp); - NicVO loadBalancingIpNic = null; - if (!revoked) { - if (mapping == null) { - // Acquire a new guest IP address and save it as the load balancing IP address - String loadBalancingIpAddress = _networkMgr.acquireGuestIpAddress(network, null); - - if (loadBalancingIpAddress == null) { - String msg = "Ran out of guest IP addresses."; - s_logger.error(msg); - throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId()); - } - - // If a NIC doesn't exist for the load balancing IP address, create one - loadBalancingIpNic = _nicDao.findByIp4Address(loadBalancingIpAddress); - if (loadBalancingIpNic == null) { - loadBalancingIpNic = savePlaceholderNic(network, loadBalancingIpAddress); - } - - // Save a mapping between the source IP address and the load balancing IP address NIC - mapping = new InlineLoadBalancerNicMapVO(rule.getId(), srcIp, loadBalancingIpNic.getId()); - _inlineLoadBalancerNicMapDao.persist(mapping); - - // On the external firewall, create a static NAT rule between the source IP address and the load balancing IP address - applyStaticNatRuleForInlineLBRule(zone, network, externalFirewall, revoked, srcIp, loadBalancingIpNic.getIp4Address()); - } else { - loadBalancingIpNic = _nicDao.findById(mapping.getNicId()); - } - } else { - if (mapping != null) { - // Find the NIC that the mapping refers to - loadBalancingIpNic = _nicDao.findById(mapping.getNicId()); - - // On the external firewall, delete the static NAT rule between the source IP address and the load balancing IP address - applyStaticNatRuleForInlineLBRule(zone, network, externalFirewall, revoked, srcIp, loadBalancingIpNic.getIp4Address()); - - // Delete the mapping between the source IP address and the load balancing IP address - _inlineLoadBalancerNicMapDao.expunge(mapping.getId()); - - // Delete the NIC - _nicDao.expunge(loadBalancingIpNic.getId()); - } else { - s_logger.debug("Revoking a rule for an inline load balancer that has not been programmed yet."); - continue; - } - } - - // Change the source IP address for the load balancing rule to be the load balancing IP address - srcIp = loadBalancingIpNic.getIp4Address(); - } - - if (destinations != null && !destinations.isEmpty()) { - LoadBalancerTO loadBalancer = new LoadBalancerTO(srcIp, srcPort, protocol, algorithm, revoked, false, destinations); - loadBalancersToApply.add(loadBalancer); - } - } - - if (loadBalancersToApply.size() > 0) { - int numLoadBalancersForCommand = loadBalancersToApply.size(); - LoadBalancerTO[] loadBalancersForCommand = loadBalancersToApply.toArray(new LoadBalancerTO[numLoadBalancersForCommand]); - LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(loadBalancersForCommand); - long guestVlanTag = Integer.parseInt(network.getBroadcastUri().getHost()); - cmd.setAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG, String.valueOf(guestVlanTag)); - Answer answer = _agentMgr.easySend(externalLoadBalancer.getId(), cmd); - if (answer == null || !answer.getResult()) { - String details = (answer != null) ? answer.getDetails() : "details unavailable"; - String msg = "Unable to apply load balancer rules to the external load balancer appliance in zone " + zone.getName() + " due to: " + details + "."; - s_logger.error(msg); - throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId()); - } - } - - return true; - } - - @Override - @Deprecated // should use more generic addNetworkDevice command to add firewall - public Host addExternalFirewall(AddExternalFirewallCmd cmd) { - Long zoneId = cmd.getZoneId(); - // AddExternalFirewallCmd support only Juniper SRX (api exists for backward compatibility) - String deviceType = NetworkDevice.JuniperSRXFirewall.getName(); - Map deviceParams = new HashMap(); - deviceParams.put(ApiConstants.USERNAME, cmd.getUsername()); - deviceParams.put(ApiConstants.URL, cmd.getUrl()); - deviceParams.put(ApiConstants.PASSWORD, cmd.getPassword()); - return addExternalFirewall(zoneId, null, deviceType, deviceParams); - } - - public Host addExternalFirewall(Long zoneId, Long physicalNetworkId, String deviceName, Map deviceParamList) { - - PhysicalNetworkVO pNetwork=null; - DataCenterVO zone =null; - NetworkDevice ntwkDevice = NetworkDevice.getNetworkDevice(deviceName); - String url=null; - String username=null; - String password=null; - - if (deviceParamList != null) { - url = (String) deviceParamList.get(ApiConstants.URL); - username = (String) deviceParamList.get(ApiConstants.USERNAME); - password = (String) deviceParamList.get(ApiConstants.PASSWORD); - } - - if (((zoneId == null) && (physicalNetworkId == null)) || (ntwkDevice == null) || (url == null) || (username == null) || (password == null) ) { - throw new InvalidParameterValueException("Atleast one of the required parameters (url, username, password," + - " zone id/physical network id) is not specified or a valid parameter."); - } - - if (physicalNetworkId != null) { - pNetwork = _physicalNetworkDao.findById(physicalNetworkId); - if (pNetwork == null) { - throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId); - } - } - - if (zoneId != null) { - zone = _dcDao.findById(zoneId); - if (zone == null) { - throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId); - } - if (pNetwork == null) { - List physicalNetworks = _physicalNetworkDao.listByZone(zoneId); - if ((physicalNetworks == null) || (physicalNetworks.size() > 1)) { - throw new InvalidParameterValueException("There are multiple physical networks configured in zone with ID: " - + zoneId + ". Physical network ID must be passed to select a physical network in this zone."); - } - pNetwork = physicalNetworks.get(0); - } - } - - PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), ntwkDevice.getNetworkServiceProvder()); - if ((ntwkSvcProvider == null ) || (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) - || (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Disabled)) { - throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() + - " is not added or in shutdown state in the physical network: " + physicalNetworkId + "to add this device" ); - } - - URI uri; - try { - uri = new URI(url); - } catch (Exception e) { - s_logger.debug(e); - throw new InvalidParameterValueException(e.getMessage()); - } - - String ipAddress = uri.getHost(); - Map params = new HashMap(); - UrlUtil.parseQueryParameters(uri.getQuery(), true, params); - String publicInterface = params.get("publicinterface"); - String usageInterface = params.get("usageinterface"); - String privateInterface = params.get("privateinterface"); - String publicZone = params.get("publiczone"); - String privateZone = params.get("privatezone"); - String numRetries = params.get("numretries"); - String timeout = params.get("timeout"); - ServerResource resource; - String guid; - - if (publicInterface == null) { - throw new InvalidParameterValueException("Please specify a public interface."); - } - - if (usageInterface != null) { - if (!usageInterface.contains(".")) { - usageInterface += ".0"; - } - } - - if (privateInterface != null) { - if (privateInterface.contains(".")) { - throw new InvalidParameterValueException("The private interface name must not have a unit identifier."); - } - } else { - throw new InvalidParameterValueException("Please specify a private interface."); - } - - if (publicZone == null) { - publicZone = "untrust"; - } - - if (privateZone == null) { - privateZone = "trust"; - } - - if (numRetries == null) { - numRetries = "1"; - } - - if (timeout == null) { - timeout = "300"; - } - - if (deviceName ==null) { - deviceName = NetworkDevice.JuniperSRXFirewall.getName(); //default it to Juniper for now - } - if (deviceName.equalsIgnoreCase(NetworkDevice.JuniperSRXFirewall.getName())) { - resource = new JuniperSrxResource(); - guid = getExternalNetworkResourceGuid(zoneId, ExternalNetworkResourceName.JuniperSrx, ipAddress); - } else { - throw new CloudRuntimeException("An unsupported networt device type is added as external firewall."); - } - - Map hostDetails = new HashMap(); - hostDetails.put("zoneId", String.valueOf(zoneId)); - hostDetails.put("ip", ipAddress); - hostDetails.put("username", username); - hostDetails.put("password", password); - hostDetails.put("publicInterface", publicInterface); - hostDetails.put("privateInterface", privateInterface); - hostDetails.put("publicZone", publicZone); - hostDetails.put("privateZone", privateZone); - hostDetails.put("numRetries", numRetries); - hostDetails.put("timeout", timeout); - hostDetails.put("guid", guid); - hostDetails.put("name", guid); - - if (usageInterface != null) { - hostDetails.put("usageInterface", usageInterface); - } - - try { - resource.configure(guid, hostDetails); - } catch (ConfigurationException e) { - throw new CloudRuntimeException(e.getMessage()); - } - - Host externalFirewall = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalFirewall, hostDetails); - if (externalFirewall != null) { - Transaction txn = Transaction.currentTxn(); - txn.start(); - _dcDao.update(zone.getId(), zone); - ExternalFirewallDeviceVO device = new ExternalFirewallDeviceVO(externalFirewall.getId(), pNetwork.getId(), ntwkSvcProvider.getProviderName()); - _externalFirewallDeviceDao.persist(device); - txn.commit(); - return externalFirewall; - } else { - return null; - } - } - - @Override - public boolean deleteExternalFirewall(DeleteExternalFirewallCmd cmd) { - return deleteExternalFirewall(cmd.getId()); - } - - public boolean deleteExternalFirewall(Long hostId) { - User caller = _accountMgr.getActiveUser(UserContext.current().getCallerUserId()); - HostVO externalFirewall = _hostDao.findById(hostId); - if (externalFirewall == null) { - throw new InvalidParameterValueException("Could not find an external firewall with ID: " + hostId); - } - - try { - // FIXME: device maintenance , rules reprogramming - if (_resourceMgr.maintain(hostId) && _resourceMgr.deleteHost(hostId, false, false)) { - return true; - } else { - return false; - } - } catch (AgentUnavailableException e) { - s_logger.debug(e); - return false; - } - } - - @Override - @Deprecated // should use more generic listNetworkDevice command - public List listExternalFirewalls(ListExternalFirewallsCmd cmd) { - List firewallHosts = new ArrayList(); - firewallHosts.addAll(listExternalFirewalls(cmd.getZoneId(), null, NetworkDevice.JuniperSRXFirewall.getName())); - return firewallHosts; - } - - public List listExternalFirewalls(Long zoneId, Long physicalNetworkId, String deviceName) { - List firewallHosts = new ArrayList(); - List firewallhostsInZone = new ArrayList(); - NetworkDevice fwNetworkDevice = NetworkDevice.getNetworkDevice(deviceName); - PhysicalNetworkVO pNetwork=null; - - if (((zoneId == null) && (physicalNetworkId == null)) || (fwNetworkDevice == null)) { - throw new InvalidParameterValueException("Atleast one of ther required parameter zone Id, physical networkId, device name is missing or invalid."); - } - - if (physicalNetworkId != null) { - pNetwork = _physicalNetworkDao.findById(physicalNetworkId); - if (pNetwork == null) { - throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId); - } - } - - if (zoneId != null) { - if (_dcDao.findById(zoneId) == null) { - throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId); - } - firewallhostsInZone.addAll(_resourceMgr.listAllHostsInOneZoneByType(Host.Type.ExternalFirewall, zoneId)); - } - if (physicalNetworkId == null) { - return firewallhostsInZone; - } - PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), fwNetworkDevice.getNetworkServiceProvder()); - if (ntwkSvcProvider == null) { - return null; - } - List fwDevices = _externalFirewallDeviceDao.listByPhysicalNetworkServiceProvider(physicalNetworkId, ntwkSvcProvider.getProviderName()); - for (ExternalFirewallDeviceVO fwDevice : fwDevices) { - firewallHosts.add(_hostDao.findById(fwDevice.getHostId())); - } - return firewallHosts; - } - - @Override - public ExternalFirewallResponse createExternalFirewallResponse(Host externalFirewall) { - Map fwDetails = _detailsDao.findDetails(externalFirewall.getId()); - ExternalFirewallResponse response = new ExternalFirewallResponse(); - response.setId(externalFirewall.getId()); - response.setIpAddress(externalFirewall.getPrivateIpAddress()); - response.setUsername(fwDetails.get("username")); - response.setPublicInterface(fwDetails.get("publicInterface")); - response.setUsageInterface(fwDetails.get("usageInterface")); - response.setPrivateInterface(fwDetails.get("privateInterface")); - response.setPublicZone(fwDetails.get("publicZone")); - response.setPrivateZone(fwDetails.get("privateZone")); - response.setNumRetries(fwDetails.get("numRetries")); - response.setTimeout(fwDetails.get("timeout")); - return response; - } - - @Override - public boolean manageGuestNetworkWithExternalFirewall(boolean add, Network network) throws ResourceUnavailableException, InsufficientCapacityException { - if (network.getTrafficType() != TrafficType.Guest) { - s_logger.trace("External firewall can only be used for add/remove guest networks."); - return false; - } - - long zoneId = network.getDataCenterId(); - DataCenterVO zone = _dcDao.findById(zoneId); - HostVO externalFirewall = null; - - if (add) { - GlobalLock deviceMapLock = GlobalLock.getInternLock("NetworkFirewallDeviceMap"); - try { - if (deviceMapLock.lock(120)) { - try { - long externalFirewallId = findSuitableFirewallDeviceForNetwork(network); - NetworkExternalFirewallVO networkFW = new NetworkExternalFirewallVO(network.getId(), externalFirewallId); - _networkExternalFirewallDao.persist(networkFW); - - ExternalFirewallDeviceVO device = _externalFirewallDeviceDao.findById(externalFirewallId); - externalFirewall = _hostDao.findById(device.getHostId()); - } finally { - deviceMapLock.unlock(); - } - } - } finally { - deviceMapLock.releaseRef(); - } - } else { - externalFirewall = getExternalFirewallForNetwork(network); - } - - Account account = _accountDao.findByIdIncludingRemoved(network.getAccountId()); - - boolean sharedSourceNat = false; - Map sourceNatCapabilities = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.SourceNat); - if (sourceNatCapabilities != null) { - String supportedSourceNatTypes = sourceNatCapabilities.get(Capability.SupportedSourceNatTypes).toLowerCase(); - if (supportedSourceNatTypes.contains("zone")) { - sharedSourceNat = true; - } - } - - IPAddressVO sourceNatIp = null; - if (!sharedSourceNat) { - // Get the source NAT IP address for this network - List sourceNatIps = _networkMgr.listPublicIpAddressesInVirtualNetwork(network.getAccountId(), zoneId, true, null); - - if (sourceNatIps.size() != 1) { - String errorMsg = "External firewall was unable to find the source NAT IP address for account " + account.getAccountName(); - s_logger.error(errorMsg); - return true; - } else { - sourceNatIp = sourceNatIps.get(0); - } - } - - // Send a command to the external firewall to implement or shutdown the guest network - long guestVlanTag = Long.parseLong(network.getBroadcastUri().getHost()); - String guestVlanGateway = network.getGateway(); - String guestVlanCidr = network.getCidr(); - String sourceNatIpAddress = sourceNatIp.getAddress().addr(); - - VlanVO publicVlan = _vlanDao.findById(sourceNatIp.getVlanId()); - String publicVlanTag = publicVlan.getVlanTag(); - - // Get network rate - Integer networkRate = _networkMgr.getNetworkRate(network.getId(), null); - - IpAddressTO ip = new IpAddressTO(account.getAccountId(), sourceNatIpAddress, add, false, !sharedSourceNat, publicVlanTag, null, null, null, null, networkRate, sourceNatIp.isOneToOneNat()); - IpAddressTO[] ips = new IpAddressTO[1]; - ips[0] = ip; - IpAssocCommand cmd = new IpAssocCommand(ips); - cmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_GATEWAY, guestVlanGateway); - cmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR, guestVlanCidr); - cmd.setAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG, String.valueOf(guestVlanTag)); - Answer answer = _agentMgr.easySend(externalFirewall.getId(), cmd); - - if (answer == null || !answer.getResult()) { - String action = add ? "implement" : "shutdown"; - String answerDetails = (answer != null) ? answer.getDetails() : "answer was null"; - String msg = "External firewall was unable to " + action + " the guest network on the external firewall in zone " + zone.getName() + " due to " + answerDetails; - s_logger.error(msg); - throw new ResourceUnavailableException(msg, DataCenter.class, zoneId); - } - - List reservedIpAddressesForGuestNetwork = _nicDao.listIpAddressInNetwork(network.getId()); - if (add && (!reservedIpAddressesForGuestNetwork.contains(network.getGateway()))) { - // Insert a new NIC for this guest network to reserve the gateway address - savePlaceholderNic(network, network.getGateway()); - } - - // Delete any mappings used for inline external load balancers in this network - List nicsInNetwork = _nicDao.listByNetworkId(network.getId()); - for (NicVO nic : nicsInNetwork) { - InlineLoadBalancerNicMapVO mapping = _inlineLoadBalancerNicMapDao.findByNicId(nic.getId()); - - if (mapping != null) { - _nicDao.expunge(mapping.getNicId()); - _inlineLoadBalancerNicMapDao.expunge(mapping.getId()); - - } - } - - - String action = add ? "implemented" : "shut down"; - s_logger.debug("External firewall has " + action + " the guest network for account " + account.getAccountName() + "(id = " + account.getAccountId() + ") with VLAN tag " + guestVlanTag); - - return true; - } - - @Override - public boolean applyFirewallRules(Network network, List rules) throws ResourceUnavailableException { - // Find the external firewall in this zone - long zoneId = network.getDataCenterId(); - DataCenterVO zone = _dcDao.findById(zoneId); - HostVO externalFirewall = getExternalFirewallForNetwork(network); - - assert(externalFirewall != null); - - if (network.getState() == Network.State.Allocated) { - s_logger.debug("External firewall was asked to apply firewall rules for network with ID " + network.getId() + "; this network is not implemented. Skipping backend commands."); - return true; - } - - List staticNatRules = new ArrayList(); - List portForwardingRules = new ArrayList(); - - for (FirewallRule rule : rules) { - IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId()); - Vlan vlan = _vlanDao.findById(sourceIp.getVlanId()); - - if (rule.getPurpose() == Purpose.StaticNat) { - StaticNatRule staticNatRule = (StaticNatRule) rule; - StaticNatRuleTO ruleTO = new StaticNatRuleTO(staticNatRule, vlan.getVlanTag(), sourceIp.getAddress().addr(), staticNatRule.getDestIpAddress()); - staticNatRules.add(ruleTO); - } else if (rule.getPurpose() == Purpose.PortForwarding) { - PortForwardingRuleTO ruleTO = new PortForwardingRuleTO((PortForwardingRule) rule, vlan.getVlanTag(), sourceIp.getAddress().addr()); - portForwardingRules.add(ruleTO); - } - } - - // Apply static nat rules - applyStaticNatRules(staticNatRules, zone, externalFirewall.getId()); - - // apply port forwarding rules - applyPortForwardingRules(portForwardingRules, zone, externalFirewall.getId()); - - return true; - } - - protected void applyStaticNatRules(List staticNatRules, DataCenter zone, long externalFirewallId) throws ResourceUnavailableException { - if (!staticNatRules.isEmpty()) { - SetStaticNatRulesCommand cmd = new SetStaticNatRulesCommand(staticNatRules); - Answer answer = _agentMgr.easySend(externalFirewallId, cmd); - if (answer == null || !answer.getResult()) { - String details = (answer != null) ? answer.getDetails() : "details unavailable"; - String msg = "External firewall was unable to apply static nat rules to the SRX appliance in zone " + zone.getName() + " due to: " + details + "."; - s_logger.error(msg); - throw new ResourceUnavailableException(msg, DataCenter.class, zone.getId()); - } - } - } - - protected void applyPortForwardingRules(List portForwardingRules, DataCenter zone, long externalFirewallId) throws ResourceUnavailableException { - if (!portForwardingRules.isEmpty()) { - SetPortForwardingRulesCommand cmd = new SetPortForwardingRulesCommand(portForwardingRules); - Answer answer = _agentMgr.easySend(externalFirewallId, cmd); - if (answer == null || !answer.getResult()) { - String details = (answer != null) ? answer.getDetails() : "details unavailable"; - String msg = "External firewall was unable to apply port forwarding rules to the SRX appliance in zone " + zone.getName() + " due to: " + details + "."; - s_logger.error(msg); - throw new ResourceUnavailableException(msg, DataCenter.class, zone.getId()); - } - } - } - - @Override - public boolean applyIps(Network network, List ipAddresses) throws ResourceUnavailableException { - return true; - } - - - @Override - public boolean manageRemoteAccessVpn(boolean create, Network network, RemoteAccessVpn vpn) throws ResourceUnavailableException { - HostVO externalFirewall = getExternalFirewallForNetwork(network); - - if (externalFirewall == null) { - return false; - } - - // Create/delete VPN - IpAddress ip = _networkMgr.getIp(vpn.getServerAddressId()); - - // Mask the IP range with the network's VLAN tag - String[] ipRange = vpn.getIpRange().split("-"); - DataCenterVO zone = _dcDao.findById(network.getDataCenterId()); - int vlanTag = Integer.parseInt(network.getBroadcastUri().getHost()); - int offset = getVlanOffset(network.getPhysicalNetworkId(), vlanTag); - int cidrSize = getGloballyConfiguredCidrSize(); - - for (int i = 0; i < 2; i++) { - ipRange[i] = NetUtils.long2Ip((NetUtils.ip2Long(ipRange[i]) & 0xff000000) | (offset << (32 - cidrSize))); - } - - String maskedIpRange = ipRange[0] + "-" + ipRange[1]; - - RemoteAccessVpnCfgCommand createVpnCmd = new RemoteAccessVpnCfgCommand(create, ip.getAddress().addr(), vpn.getLocalIp(), maskedIpRange, vpn.getIpsecPresharedKey()); - createVpnCmd.setAccessDetail(NetworkElementCommand.ACCOUNT_ID, String.valueOf(network.getAccountId())); - createVpnCmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr()); - Answer answer = _agentMgr.easySend(externalFirewall.getId(), createVpnCmd); - if (answer == null || !answer.getResult()) { - String details = (answer != null) ? answer.getDetails() : "details unavailable"; - String msg = "External firewall was unable to create a remote access VPN in zone " + zone.getName() + " due to: " + details + "."; - s_logger.error(msg); - throw new ResourceUnavailableException(msg, DataCenter.class, zone.getId()); - } - - // Add/delete users - List vpnUsers = _vpnUsersDao.listByAccount(vpn.getAccountId()); - return manageRemoteAccessVpnUsers(network, vpn, vpnUsers); - } - - @Override - public boolean manageRemoteAccessVpnUsers(Network network, RemoteAccessVpn vpn, List vpnUsers) throws ResourceUnavailableException { - HostVO externalFirewall = getExternalFirewallForNetwork(network); - - if (externalFirewall == null) { - return false; - } - - List addUsers = new ArrayList(); - List removeUsers = new ArrayList(); - for (VpnUser user : vpnUsers) { - if (user.getState() == VpnUser.State.Add || - user.getState() == VpnUser.State.Active) { - addUsers.add(user); - } else if (user.getState() == VpnUser.State.Revoke) { - removeUsers.add(user); - } - } - - VpnUsersCfgCommand addUsersCmd = new VpnUsersCfgCommand(addUsers, removeUsers); - addUsersCmd.setAccessDetail(NetworkElementCommand.ACCOUNT_ID, String.valueOf(network.getAccountId())); - addUsersCmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr()); - - Answer answer = _agentMgr.easySend(externalFirewall.getId(), addUsersCmd); - if (answer == null || !answer.getResult()) { - String details = (answer != null) ? answer.getDetails() : "details unavailable"; - DataCenterVO zone = _dcDao.findById(network.getDataCenterId()); - String msg = "External firewall was unable to add remote access users in zone " + zone.getName() + " due to: " + details + "."; - s_logger.error(msg); - throw new ResourceUnavailableException(msg, DataCenter.class, zone.getId()); - } - - return true; - } - - private void applyStaticNatRuleForInlineLBRule(DataCenterVO zone, Network network, HostVO externalFirewall, boolean revoked, String publicIp, String privateIp) throws ResourceUnavailableException { - List staticNatRules = new ArrayList(); - IPAddressVO ipVO = _ipAddressDao.listByDcIdIpAddress(zone.getId(), publicIp).get(0); - VlanVO vlan = _vlanDao.findById(ipVO.getVlanId()); - FirewallRuleVO fwRule = new FirewallRuleVO(null, ipVO.getId(), -1, -1, "any", network.getId(), network.getAccountId(), network.getDomainId(), Purpose.StaticNat, null, null, null, null); - FirewallRule.State state = !revoked ? FirewallRule.State.Add : FirewallRule.State.Revoke; - fwRule.setState(state); - StaticNatRule rule = new StaticNatRuleImpl(fwRule, privateIp); - StaticNatRuleTO ruleTO = new StaticNatRuleTO(rule, vlan.getVlanTag(), publicIp, privateIp); - staticNatRules.add(ruleTO); - - applyStaticNatRules(staticNatRules, zone, externalFirewall.getId()); - } - - private boolean externalLoadBalancerIsInline(HostVO externalLoadBalancer) { - DetailVO detail = _detailsDao.findDetail(externalLoadBalancer.getId(), "inline"); - return (detail != null && detail.getValue().equals("true")); - } - - @Override - public int getVlanOffset(long physicalNetworkId, int vlanTag) { - PhysicalNetworkVO pNetwork = _physicalNetworkDao.findById(physicalNetworkId); - if (pNetwork == null) { - throw new CloudRuntimeException("Could not find the physical Network " + physicalNetworkId + "."); - } - - if (pNetwork.getVnet() == null) { - throw new CloudRuntimeException("Could not find vlan range for physical Network " + physicalNetworkId + "."); - } - String vlanRange[] = pNetwork.getVnet().split("-"); - int lowestVlanTag = Integer.valueOf(vlanRange[0]); - return vlanTag - lowestVlanTag; - } - - private NicVO savePlaceholderNic(Network network, String ipAddress) { - NicVO nic = new NicVO(null, null, network.getId(), null); - nic.setIp4Address(ipAddress); - nic.setReservationStrategy(ReservationStrategy.PlaceHolder); - nic.setState(State.Reserved); - return _nicDao.persist(nic); - } - - @Override - public int getGloballyConfiguredCidrSize() { - try { - String globalVlanBits = _configDao.getValue(Config.GuestVlanBits.key()); - return 8 + Integer.parseInt(globalVlanBits); - } catch (Exception e) { - throw new CloudRuntimeException("Failed to read the globally configured VLAN bits size."); - } - } - - protected class ExternalNetworkUsageTask implements Runnable { - - public ExternalNetworkUsageTask() { - } - - private boolean updateBytes(UserStatisticsVO userStats, long newCurrentBytesSent, long newCurrentBytesReceived) { - long oldNetBytesSent = userStats.getNetBytesSent(); - long oldNetBytesReceived = userStats.getNetBytesReceived(); - long oldCurrentBytesSent = userStats.getCurrentBytesSent(); - long oldCurrentBytesReceived = userStats.getCurrentBytesReceived(); - String warning = "Received an external network stats byte count that was less than the stored value. Zone ID: " + userStats.getDataCenterId() + ", account ID: " + userStats.getAccountId() + "."; - - userStats.setCurrentBytesSent(newCurrentBytesSent); - if (oldCurrentBytesSent > newCurrentBytesSent) { - s_logger.warn(warning + "Stored bytes sent: " + oldCurrentBytesSent + ", new bytes sent: " + newCurrentBytesSent + "."); - userStats.setNetBytesSent(oldNetBytesSent + oldCurrentBytesSent); - } - - userStats.setCurrentBytesReceived(newCurrentBytesReceived); - if (oldCurrentBytesReceived > newCurrentBytesReceived) { - s_logger.warn(warning + "Stored bytes received: " + oldCurrentBytesReceived + ", new bytes received: " + newCurrentBytesReceived + "."); - userStats.setNetBytesReceived(oldNetBytesReceived + oldCurrentBytesReceived); - } - - return _userStatsDao.update(userStats.getId(), userStats); - } - - /* - * Creates a new stats entry for the specified parameters, if one doesn't already exist. - */ - private boolean createStatsEntry(long accountId, long zoneId, long networkId, String publicIp, long hostId) { - HostVO host = _hostDao.findById(hostId); - UserStatisticsVO userStats = _userStatsDao.findBy(accountId, zoneId, networkId, publicIp, hostId, host.getType().toString()); - if (userStats == null) { - return (_userStatsDao.persist(new UserStatisticsVO(accountId, zoneId, publicIp, hostId, host.getType().toString(), networkId)) != null); - } else { - return true; - } - } - - /* - * Updates an existing stats entry with new data from the specified usage answer. - */ - private boolean updateStatsEntry(long accountId, long zoneId, long networkId, String publicIp, long hostId, ExternalNetworkResourceUsageAnswer answer) { - AccountVO account = _accountDao.findById(accountId); - DataCenterVO zone = _dcDao.findById(zoneId); - NetworkVO network = _networkDao.findById(networkId); - HostVO host = _hostDao.findById(hostId); - String statsEntryIdentifier = "account " + account.getAccountName() + ", zone " + zone.getName() + ", network ID " + networkId + ", host ID " + host.getName(); - - long newCurrentBytesSent = 0; - long newCurrentBytesReceived = 0; - - if (publicIp != null) { - long[] bytesSentAndReceived = null; - statsEntryIdentifier += ", public IP: " + publicIp; - - if (host.getType().equals(Host.Type.ExternalLoadBalancer) && externalLoadBalancerIsInline(host)) { - // Look up stats for the guest IP address that's mapped to the public IP address - InlineLoadBalancerNicMapVO mapping = _inlineLoadBalancerNicMapDao.findByPublicIpAddress(publicIp); - - if (mapping != null) { - NicVO nic = _nicDao.findById(mapping.getNicId()); - String loadBalancingIpAddress = nic.getIp4Address(); - bytesSentAndReceived = answer.ipBytes.get(loadBalancingIpAddress); - - if (bytesSentAndReceived != null) { - bytesSentAndReceived[0] = 0; - } - } - } else { - bytesSentAndReceived = answer.ipBytes.get(publicIp); - } - - if (bytesSentAndReceived == null) { - s_logger.debug("Didn't get an external network usage answer for public IP " + publicIp); - } else { - newCurrentBytesSent += bytesSentAndReceived[0]; - newCurrentBytesReceived += bytesSentAndReceived[1]; - } - } else { - URI broadcastURI = network.getBroadcastUri(); - if (broadcastURI == null) { - s_logger.debug("Not updating stats for guest network with ID " + network.getId() + " because the network is not implemented."); - return true; - } else { - long vlanTag = Integer.parseInt(broadcastURI.getHost()); - long[] bytesSentAndReceived = answer.guestVlanBytes.get(String.valueOf(vlanTag)); - - if (bytesSentAndReceived == null) { - s_logger.warn("Didn't get an external network usage answer for guest VLAN " + vlanTag); - } else { - newCurrentBytesSent += bytesSentAndReceived[0]; - newCurrentBytesReceived += bytesSentAndReceived[1]; - } - } - } - - UserStatisticsVO userStats; - try { - userStats = _userStatsDao.lock(accountId, zoneId, networkId, publicIp, hostId, host.getType().toString()); - } catch (Exception e) { - s_logger.warn("Unable to find user stats entry for " + statsEntryIdentifier); - return false; - } - - if (updateBytes(userStats, newCurrentBytesSent, newCurrentBytesReceived)) { - s_logger.debug("Successfully updated stats for " + statsEntryIdentifier); - return true; - } else { - s_logger.debug("Failed to update stats for " + statsEntryIdentifier); - return false; - } - } - - private boolean createOrUpdateStatsEntry(boolean create, long accountId, long zoneId, long networkId, String publicIp, long hostId, ExternalNetworkResourceUsageAnswer answer) { - if (create) { - return createStatsEntry(accountId, zoneId, networkId, publicIp, hostId); - } else { - return updateStatsEntry(accountId, zoneId, networkId, publicIp, hostId, answer); - } - } - - /* - * Creates/updates all necessary stats entries for an account and zone. - * Stats entries are created for source NAT IP addresses, static NAT rules, port forwarding rules, and load balancing rules - */ - private boolean manageStatsEntries(boolean create, long accountId, long zoneId, Network network, - HostVO externalFirewall, ExternalNetworkResourceUsageAnswer firewallAnswer, - HostVO externalLoadBalancer, ExternalNetworkResourceUsageAnswer lbAnswer) { - String accountErrorMsg = "Failed to update external network stats entry. Details: account ID = " + accountId; - Transaction txn = Transaction.open(Transaction.CLOUD_DB); - try { - txn.start(); - String networkErrorMsg = accountErrorMsg + ", network ID = " + network.getId(); - - boolean sharedSourceNat = false; - Map sourceNatCapabilities = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.SourceNat); - if (sourceNatCapabilities != null) { - String supportedSourceNatTypes = sourceNatCapabilities.get(Capability.SupportedSourceNatTypes).toLowerCase(); - if (supportedSourceNatTypes.contains("zone")) { - sharedSourceNat = true; - } - } - - if (!sharedSourceNat) { - // Manage the entry for this network's source NAT IP address - List sourceNatIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), true); - if (sourceNatIps.size() == 1) { - String publicIp = sourceNatIps.get(0).getAddress().addr(); - if (!createOrUpdateStatsEntry(create, accountId, zoneId, network.getId(), publicIp, externalFirewall.getId(), firewallAnswer)) { - throw new ExecutionException(networkErrorMsg + ", source NAT IP = " + publicIp); - } - } - - // Manage one entry for each static NAT rule in this network - List staticNatIps = _ipAddressDao.listStaticNatPublicIps(network.getId()); - for (IPAddressVO staticNatIp : staticNatIps) { - String publicIp = staticNatIp.getAddress().addr(); - if (!createOrUpdateStatsEntry(create, accountId, zoneId, network.getId(), publicIp, externalFirewall.getId(), firewallAnswer)) { - throw new ExecutionException(networkErrorMsg + ", static NAT rule public IP = " + publicIp); - } - } - - // Manage one entry for each port forwarding rule in this network - List portForwardingRules = _portForwardingRulesDao.listByNetwork(network.getId()); - for (PortForwardingRuleVO portForwardingRule : portForwardingRules) { - String publicIp = _networkMgr.getIp(portForwardingRule.getSourceIpAddressId()).getAddress().addr(); - if (!createOrUpdateStatsEntry(create, accountId, zoneId, network.getId(), publicIp, externalFirewall.getId(), firewallAnswer)) { - throw new ExecutionException(networkErrorMsg + ", port forwarding rule public IP = " + publicIp); - } - } - } else { - // Manage the account-wide entry for the external firewall - if (!createOrUpdateStatsEntry(create, accountId, zoneId, network.getId(), null, externalFirewall.getId(), firewallAnswer)) { - throw new ExecutionException(networkErrorMsg); - } - } - - // If an external load balancer is added, manage one entry for each load balancing rule in this network - if (externalLoadBalancer != null && lbAnswer != null) { - List loadBalancers = _loadBalancerDao.listByNetworkId(network.getId()); - for (LoadBalancerVO loadBalancer : loadBalancers) { - String publicIp = _networkMgr.getIp(loadBalancer.getSourceIpAddressId()).getAddress().addr(); - if (!createOrUpdateStatsEntry(create, accountId, zoneId, network.getId(), publicIp, externalLoadBalancer.getId(), lbAnswer)) { - throw new ExecutionException(networkErrorMsg + ", load balancing rule public IP = " + publicIp); - } - } - } - return txn.commit(); - } catch (Exception e) { - s_logger.warn("Exception: ", e); - txn.rollback(); - return false; - } finally { - txn.close(); - } - } - - private void runExternalNetworkUsageTask() { - s_logger.debug("External network stats collector is running..."); - - for (DataCenterVO zone : _dcDao.listAll()) { - List domainRoutersInZone = _routerDao.listByDataCenter(zone.getId()); - for (DomainRouterVO domainRouter : domainRoutersInZone) { - long accountId = domainRouter.getAccountId(); - long zoneId = zone.getId(); - List networksForAccount = _networkDao.listBy(accountId, zoneId, Network.GuestType.Isolated); - - for (NetworkVO network : networksForAccount) { - if (!_networkMgr.networkIsConfiguredForExternalNetworking(zoneId, network.getId())) { - s_logger.debug("Network " + network.getId() + " is not configured for external networking, so skipping usage check."); - continue; - } - - HostVO externalFirewall = getExternalFirewallForNetwork(network); - HostVO externalLoadBalancer = getExternalLoadBalancerForNetwork(network); - - s_logger.debug("Collecting external network stats for network " + network.getId()); - - ExternalNetworkResourceUsageCommand cmd = new ExternalNetworkResourceUsageCommand(); - - // Get network stats from the external firewall - ExternalNetworkResourceUsageAnswer firewallAnswer = null; - if (externalFirewall != null) { - firewallAnswer = (ExternalNetworkResourceUsageAnswer) _agentMgr.easySend(externalFirewall.getId(), cmd); - if (firewallAnswer == null || !firewallAnswer.getResult()) { - String details = (firewallAnswer != null) ? firewallAnswer.getDetails() : "details unavailable"; - String msg = "Unable to get external firewall stats for " + zone.getName() + " due to: " + details + "."; - s_logger.error(msg); - continue; - } - } - - // Get network stats from the external load balancer - ExternalNetworkResourceUsageAnswer lbAnswer = null; - if (externalLoadBalancer != null) { - lbAnswer = (ExternalNetworkResourceUsageAnswer) _agentMgr.easySend(externalLoadBalancer.getId(), cmd); - if (lbAnswer == null || !lbAnswer.getResult()) { - String details = (lbAnswer != null) ? lbAnswer.getDetails() : "details unavailable"; - String msg = "Unable to get external load balancer stats for " + zone.getName() + " due to: " + details + "."; - s_logger.error(msg); - } - } - - AccountVO account = _accountDao.findById(accountId); - if (account == null) { - s_logger.debug("Skipping stats update for account with ID " + accountId); - continue; - } - - if (!manageStatsEntries(true, accountId, zoneId, network, externalFirewall, firewallAnswer, externalLoadBalancer, lbAnswer)) { - continue; - } - - manageStatsEntries(false, accountId, zoneId, network, externalFirewall, firewallAnswer, externalLoadBalancer, lbAnswer); - } - } - } - } - - @Override - public void run() { - GlobalLock scanLock = GlobalLock.getInternLock("ExternalNetworkManagerImpl"); - try { - if (scanLock.lock(20)) { - try { - runExternalNetworkUsageTask(); - } finally { - scanLock.unlock(); - } - } - } catch (Exception e) { - s_logger.warn("Problems while getting external network usage", e); - } finally { - scanLock.releaseRef(); - } - } + HostVO device = _hostDao.findById(cmd.getId()); + if (device.getType() == Type.ExternalLoadBalancer) { + ExternalLoadBalancerDeviceManager lbDeviceMgr = (ExternalLoadBalancerDeviceManager) _f5LbElementService; + return lbDeviceMgr.deleteExternalLoadBalancer(cmd.getId()); + } else if (device.getType() == Type.ExternalLoadBalancer) { + ExternalFirewallDeviceManager fwDeviceManager = (ExternalFirewallDeviceManager) _srxElementService; + return fwDeviceManager.deleteExternalFirewall(cmd.getId()); + } + return true; } } diff --git a/server/src/com/cloud/network/NetworkExternalFirewallVO.java b/server/src/com/cloud/network/NetworkExternalFirewallVO.java index 9cba5dc1186..95131fa9447 100644 --- a/server/src/com/cloud/network/NetworkExternalFirewallVO.java +++ b/server/src/com/cloud/network/NetworkExternalFirewallVO.java @@ -18,6 +18,9 @@ package com.cloud.network; +import java.util.Date; +import java.util.UUID; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -25,11 +28,12 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; +import com.cloud.utils.db.GenericDao; + /** * NetworkExternalFirewallVO contains information on the networks that are using external firewall */ - @Entity @Table(name="network_external_firewall_device_map") public class NetworkExternalFirewallVO { @@ -38,19 +42,29 @@ public class NetworkExternalFirewallVO { @Column(name = "id") private long id; + @Column(name="uuid") + private String uuid; + @Column(name = "network_id") private long networkId; @Column(name = "external_firewall_device_id") private long externalFirewallDeviceId; + @Column(name=GenericDao.CREATED_COLUMN) + Date created; + + @Column(name=GenericDao.REMOVED_COLUMN) + Date removed; + public NetworkExternalFirewallVO(long networkId, long externalFirewallDeviceId) { this.networkId = networkId; this.externalFirewallDeviceId = externalFirewallDeviceId; + this.uuid = UUID.randomUUID().toString(); } public NetworkExternalFirewallVO() { - + this.uuid = UUID.randomUUID().toString(); } public long getId() { @@ -65,4 +79,11 @@ public class NetworkExternalFirewallVO { return externalFirewallDeviceId; } + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } } diff --git a/server/src/com/cloud/network/NetworkExternalLoadBalancerVO.java b/server/src/com/cloud/network/NetworkExternalLoadBalancerVO.java index 17ecd3d5de3..6fe2f42069c 100644 --- a/server/src/com/cloud/network/NetworkExternalLoadBalancerVO.java +++ b/server/src/com/cloud/network/NetworkExternalLoadBalancerVO.java @@ -18,6 +18,7 @@ package com.cloud.network; import java.util.Date; +import java.util.UUID; import javax.persistence.Column; import javax.persistence.Entity; @@ -29,7 +30,7 @@ import javax.persistence.Table; import com.cloud.utils.db.GenericDao; /** - * NetworkExternalLoadBalancerVO contains information on the networks that are using external load balancers + * NetworkExternalLoadBalancerVO contains mapping of a network and the external load balancer device id assigned to the network */ @Entity @@ -41,15 +42,15 @@ public class NetworkExternalLoadBalancerVO { @Column(name = "id") private long id; + @Column(name="uuid") + private String uuid; + @Column(name = "network_id") private long networkId; @Column(name = "external_load_balancer_device_id") private long externalLBDeviceId; - @Column(name = "subscribed_capacity") - private long subscribedCapacity; - @Column(name=GenericDao.CREATED_COLUMN) Date created; @@ -59,15 +60,11 @@ public class NetworkExternalLoadBalancerVO { public NetworkExternalLoadBalancerVO(long networkId, long externalLBDeviceID) { this.networkId = networkId; this.externalLBDeviceId = externalLBDeviceID; - this.subscribedCapacity = 0; - } - public NetworkExternalLoadBalancerVO(long networkId, long externalLBDeviceID, long subscribedCapacity) { - this(networkId, externalLBDeviceID); - this.subscribedCapacity = subscribedCapacity; + this.uuid = UUID.randomUUID().toString(); } public NetworkExternalLoadBalancerVO(){ - + this.uuid = UUID.randomUUID().toString(); } public long getId() { @@ -82,7 +79,11 @@ public class NetworkExternalLoadBalancerVO { return externalLBDeviceId; } - public long getSubscribedCapacity() { - return subscribedCapacity; + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; } } diff --git a/server/src/com/cloud/network/dao/ExternalFirewallDeviceDao.java b/server/src/com/cloud/network/dao/ExternalFirewallDeviceDao.java index 84719666e26..ed765f3c699 100644 --- a/server/src/com/cloud/network/dao/ExternalFirewallDeviceDao.java +++ b/server/src/com/cloud/network/dao/ExternalFirewallDeviceDao.java @@ -20,9 +20,42 @@ package com.cloud.network.dao; import java.util.List; import com.cloud.network.ExternalFirewallDeviceVO; +import com.cloud.network.ExternalFirewallDeviceVO.FirewallDeviceAllocationState; +import com.cloud.network.ExternalFirewallDeviceVO.FirewallDeviceState; import com.cloud.utils.db.GenericDao; public interface ExternalFirewallDeviceDao extends GenericDao { - List listByPhysicalNetworkServiceProvider(long physicalNetworkId, String provider_name); + + /** + * list all the firewall devices added in to this physical network? + * @param physicalNetworkId physical Network Id + * @return list of ExternalFirewallDeviceVO for the devices added in to this physical network. + */ List listByPhysicalNetwork(long physicalNetworkId); + + /** + * list the firewall devices added in to this physical network of certain provider type? + * @param physicalNetworkId physical Network Id + * @param provider_name netwrok service provider name + * @return list of ExternalFirewallDeviceVO for the devices in the physical network of a provider type + */ + List listByPhysicalNetworkAndProvider(long physicalNetworkId, String provider_name); + + /** + * list the firewall devices added in to this physical network by their allocation state + * @param physicalNetworkId physical Network Id + * @param provider_name netwrok service provider name + * @param allocationState firewall device allocation state + * @return list of ExternalFirewallDeviceVO for the devices in the physical network with a device allocation state + */ + List listByProviderAndDeviceAllocationState(long physicalNetworkId, String provider_name, FirewallDeviceAllocationState allocationState); + + /** + * list the load balancer devices added in to this physical network by the device status (enabled/disabled) + * @param physicalNetworkId physical Network Id + * @param provider_name netwrok service provider name + * @param state firewall device status + * @return list of ExternalFirewallDeviceVO for the devices in the physical network with a device state + */ + List listByProviderAndDeviceStaus(long physicalNetworkId, String provider_name, FirewallDeviceState state); } diff --git a/server/src/com/cloud/network/dao/ExternalFirewallDeviceDaoImpl.java b/server/src/com/cloud/network/dao/ExternalFirewallDeviceDaoImpl.java index db87e104d7d..7e048105805 100644 --- a/server/src/com/cloud/network/dao/ExternalFirewallDeviceDaoImpl.java +++ b/server/src/com/cloud/network/dao/ExternalFirewallDeviceDaoImpl.java @@ -21,6 +21,8 @@ package com.cloud.network.dao; import java.util.List; import javax.ejb.Local; import com.cloud.network.ExternalFirewallDeviceVO; +import com.cloud.network.ExternalFirewallDeviceVO.FirewallDeviceAllocationState; +import com.cloud.network.ExternalFirewallDeviceVO.FirewallDeviceState; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; @@ -31,16 +33,30 @@ import com.cloud.utils.db.SearchCriteria.Op; public class ExternalFirewallDeviceDaoImpl extends GenericDaoBase implements ExternalFirewallDeviceDao { final SearchBuilder physicalNetworkServiceProviderSearch; final SearchBuilder physicalNetworkIdSearch; + final SearchBuilder allocationStateSearch; + final SearchBuilder deviceStatusSearch; protected ExternalFirewallDeviceDaoImpl() { + physicalNetworkIdSearch = createSearchBuilder(); + physicalNetworkIdSearch.and("physicalNetworkId", physicalNetworkIdSearch.entity().getPhysicalNetworkId(), Op.EQ); + physicalNetworkIdSearch.done(); + physicalNetworkServiceProviderSearch = createSearchBuilder(); physicalNetworkServiceProviderSearch.and("physicalNetworkId", physicalNetworkServiceProviderSearch.entity().getPhysicalNetworkId(), Op.EQ); physicalNetworkServiceProviderSearch.and("networkServiceProviderName", physicalNetworkServiceProviderSearch.entity().getProviderName(), Op.EQ); physicalNetworkServiceProviderSearch.done(); - physicalNetworkIdSearch = createSearchBuilder(); - physicalNetworkIdSearch.and("physicalNetworkId", physicalNetworkIdSearch.entity().getPhysicalNetworkId(), Op.EQ); - physicalNetworkIdSearch.done(); + allocationStateSearch = createSearchBuilder(); + allocationStateSearch.and("physicalNetworkId", allocationStateSearch.entity().getPhysicalNetworkId(), Op.EQ); + allocationStateSearch.and("providerName", allocationStateSearch.entity().getProviderName(), Op.EQ); + allocationStateSearch.and("allocationState", allocationStateSearch.entity().getAllocationState(), Op.EQ); + allocationStateSearch.done(); + + deviceStatusSearch = createSearchBuilder(); + deviceStatusSearch.and("physicalNetworkId", deviceStatusSearch.entity().getPhysicalNetworkId(), Op.EQ); + deviceStatusSearch.and("providerName", deviceStatusSearch.entity().getProviderName(), Op.EQ); + deviceStatusSearch.and("deviceState", deviceStatusSearch.entity().getState(), Op.EQ); + deviceStatusSearch.done(); } @Override @@ -51,10 +67,29 @@ public class ExternalFirewallDeviceDaoImpl extends GenericDaoBase listByPhysicalNetworkServiceProvider(long physicalNetworkId, String providerName) { + public List listByPhysicalNetworkAndProvider(long physicalNetworkId, String providerName) { SearchCriteria sc = physicalNetworkServiceProviderSearch.create(); + sc.setParameters("physicalNetworkId", physicalNetworkId); sc.setParameters("networkServiceProviderName", providerName); return search(sc, null); } + @Override + public List listByProviderAndDeviceAllocationState(long physicalNetworkId, String providerName, FirewallDeviceAllocationState allocationState) { + SearchCriteria sc = allocationStateSearch.create(); + sc.setParameters("physicalNetworkId", physicalNetworkId); + sc.setParameters("providerName", providerName); + sc.setParameters("allocationState", allocationState); + return search(sc, null); + } + + @Override + public List listByProviderAndDeviceStaus(long physicalNetworkId, String providerName, FirewallDeviceState state) { + SearchCriteria sc = deviceStatusSearch.create(); + sc.setParameters("physicalNetworkId", physicalNetworkId); + sc.setParameters("providerName", providerName); + sc.setParameters("deviceState", state); + return search(sc, null); + } + } diff --git a/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDao.java b/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDao.java index e7d8b464b54..ad6a8b68323 100644 --- a/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDao.java +++ b/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDao.java @@ -21,12 +21,50 @@ package com.cloud.network.dao; import java.util.List; import com.cloud.network.ExternalLoadBalancerDeviceVO; import com.cloud.network.ExternalLoadBalancerDeviceVO.LBDeviceAllocationState; +import com.cloud.network.ExternalLoadBalancerDeviceVO.LBDeviceState; import com.cloud.utils.db.GenericDao; public interface ExternalLoadBalancerDeviceDao extends GenericDao { - List listByPhysicalNetworkServiceProvider(long physicalNetworkId, String provider_name); + /** + * list all the load balancer devices added in to this physical network? + * @param physicalNetworkId physical Network Id + * @return list of ExternalLoadBalancerDeviceVO for the devices in the physical network. + */ List listByPhysicalNetwork(long physicalNetworkId); - List listByDeviceAllocationState(long physicalNetworkId, String provider_name, LBDeviceAllocationState state); + /** + * list the load balancer devices added in to this physical network of certain provider type? + * @param physicalNetworkId physical Network Id + * @param provider_name netwrok service provider name + * @return list of ExternalLoadBalancerDeviceVO for the devices in the physical network of a provider type + */ + List listByPhysicalNetworkAndProvider(long physicalNetworkId, String provider_name); + + /** + * list the load balancer devices added in to this physical network by their allocation state + * @param physicalNetworkId physical Network Id + * @param provider_name netwrok service provider name + * @param allocationState load balancer device allocation state + * @return list of ExternalLoadBalancerDeviceVO for the devices in the physical network with a device allocation state + */ + List listByProviderAndDeviceAllocationState(long physicalNetworkId, String provider_name, LBDeviceAllocationState allocationState); + + /** + * list the load balancer devices added in to this physical network by the device status (enabled/disabled) + * @param physicalNetworkId physical Network Id + * @param provider_name netwrok service provider name + * @param state load balancer device status + * @return list of ExternalLoadBalancerDeviceVO for the devices in the physical network with a device state + */ + List listByProviderAndDeviceStaus(long physicalNetworkId, String provider_name, LBDeviceState state); + + /** + * list the load balancer devices added in to this physical network by the managed type (external/cloudstack managed) + * @param physicalNetworkId physical Network Id + * @param provider_name netwrok service provider name + * @param managed managed type + * @return list of ExternalLoadBalancerDeviceVO for the devices in to this physical network of a managed type + */ + List listByProviderAndManagedType(long physicalNetworkId, String provider_name, boolean managed); } diff --git a/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDaoImpl.java b/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDaoImpl.java index f41510e7fd5..08e1356104d 100644 --- a/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDaoImpl.java +++ b/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDaoImpl.java @@ -22,6 +22,7 @@ import java.util.List; import javax.ejb.Local; import com.cloud.network.ExternalLoadBalancerDeviceVO; import com.cloud.network.ExternalLoadBalancerDeviceVO.LBDeviceAllocationState; +import com.cloud.network.ExternalLoadBalancerDeviceVO.LBDeviceState; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; @@ -30,28 +31,43 @@ import com.cloud.utils.db.SearchCriteria.Op; @Local(value=ExternalLoadBalancerDeviceDao.class) @DB(txn=false) public class ExternalLoadBalancerDeviceDaoImpl extends GenericDaoBase implements ExternalLoadBalancerDeviceDao { - final SearchBuilder physicalNetworkServiceProviderSearch; final SearchBuilder physicalNetworkIdSearch; + final SearchBuilder physicalNetworkServiceProviderSearch; final SearchBuilder allocationStateSearch; + final SearchBuilder deviceStatusSearch; + final SearchBuilder deviceManagedTypeSearch; public ExternalLoadBalancerDeviceDaoImpl() { super(); - physicalNetworkServiceProviderSearch = createSearchBuilder(); - physicalNetworkServiceProviderSearch.and("physicalNetworkId", physicalNetworkServiceProviderSearch.entity().getPhysicalNetworkId(), Op.EQ); - physicalNetworkServiceProviderSearch.and("provider_name", physicalNetworkServiceProviderSearch.entity().getProviderName(), Op.EQ); - physicalNetworkServiceProviderSearch.done(); physicalNetworkIdSearch = createSearchBuilder(); physicalNetworkIdSearch.and("physicalNetworkId", physicalNetworkIdSearch.entity().getPhysicalNetworkId(), Op.EQ); physicalNetworkIdSearch.done(); + physicalNetworkServiceProviderSearch = createSearchBuilder(); + physicalNetworkServiceProviderSearch.and("physicalNetworkId", physicalNetworkServiceProviderSearch.entity().getPhysicalNetworkId(), Op.EQ); + physicalNetworkServiceProviderSearch.and("providerName", physicalNetworkServiceProviderSearch.entity().getProviderName(), Op.EQ); + physicalNetworkServiceProviderSearch.done(); + allocationStateSearch = createSearchBuilder(); allocationStateSearch.and("physicalNetworkId", allocationStateSearch.entity().getPhysicalNetworkId(), Op.EQ); + allocationStateSearch.and("providerName", allocationStateSearch.entity().getProviderName(), Op.EQ); allocationStateSearch.and("allocationState", allocationStateSearch.entity().getAllocationState(), Op.EQ); allocationStateSearch.done(); + + deviceStatusSearch = createSearchBuilder(); + deviceStatusSearch.and("physicalNetworkId", deviceStatusSearch.entity().getPhysicalNetworkId(), Op.EQ); + deviceStatusSearch.and("providerName", deviceStatusSearch.entity().getProviderName(), Op.EQ); + deviceStatusSearch.and("deviceState", deviceStatusSearch.entity().getState(), Op.EQ); + deviceStatusSearch.done(); + + deviceManagedTypeSearch = createSearchBuilder(); + deviceManagedTypeSearch.and("physicalNetworkId", deviceManagedTypeSearch.entity().getPhysicalNetworkId(), Op.EQ); + deviceManagedTypeSearch.and("providerName", deviceManagedTypeSearch.entity().getProviderName(), Op.EQ); + deviceManagedTypeSearch.and("managedType", deviceManagedTypeSearch.entity().getIsManagedDevice(), Op.EQ); + deviceManagedTypeSearch.done(); } - @Override public List listByPhysicalNetwork(long physicalNetworkId) { SearchCriteria sc = physicalNetworkIdSearch.create(); sc.setParameters("physicalNetworkId", physicalNetworkId); @@ -59,19 +75,37 @@ public class ExternalLoadBalancerDeviceDaoImpl extends GenericDaoBase listByPhysicalNetworkServiceProvider(long physicalNetworkId, String provider_name) { + public List listByPhysicalNetworkAndProvider(long physicalNetworkId, String provider_name) { SearchCriteria sc = physicalNetworkServiceProviderSearch.create(); sc.setParameters("physicalNetworkId", physicalNetworkId); - sc.setParameters("provider_name", provider_name); + sc.setParameters("providerName", provider_name); return search(sc, null); } @Override - public List listByDeviceAllocationState(long physicalNetworkId, String provider_name, LBDeviceAllocationState state) { + public List listByProviderAndDeviceAllocationState(long physicalNetworkId, String provider_name, LBDeviceAllocationState state) { SearchCriteria sc = allocationStateSearch.create(); sc.setParameters("physicalNetworkId", physicalNetworkId); - sc.setParameters("provider_name", provider_name); + sc.setParameters("providerName", provider_name); sc.setParameters("allocationState", state); return search(sc, null); } + + @Override + public List listByProviderAndDeviceStaus(long physicalNetworkId, String providerName, LBDeviceState state) { + SearchCriteria sc = deviceStatusSearch.create(); + sc.setParameters("physicalNetworkId", physicalNetworkId); + sc.setParameters("providerName", providerName); + sc.setParameters("deviceState", state); + return search(sc, null); + } + + @Override + public List listByProviderAndManagedType(long physicalNetworkId, String providerName, boolean managed) { + SearchCriteria sc = deviceManagedTypeSearch.create(); + sc.setParameters("physicalNetworkId", physicalNetworkId); + sc.setParameters("providerName", providerName); + sc.setParameters("managedType", managed); + return search(sc, null); + } } diff --git a/server/src/com/cloud/network/dao/NetworkExternalFirewallDao.java b/server/src/com/cloud/network/dao/NetworkExternalFirewallDao.java index f4ad7aa5e62..6719aa7f708 100644 --- a/server/src/com/cloud/network/dao/NetworkExternalFirewallDao.java +++ b/server/src/com/cloud/network/dao/NetworkExternalFirewallDao.java @@ -24,6 +24,18 @@ import com.cloud.network.NetworkExternalFirewallVO; import com.cloud.utils.db.GenericDao; public interface NetworkExternalFirewallDao extends GenericDao { + + /** + * find the network to firewall device mapping corresponding to a network + * @param lbDeviceId guest network Id + * @return return NetworkExternalFirewallDao for the guest network + */ NetworkExternalFirewallVO findByNetworkId(long networkId); + + /** + * list all network to firewall device mappings corresponding to a firewall device Id + * @param lbDeviceId firewall device Id + * @return list of NetworkExternalFirewallVO mappings corresponding to the networks mapped to the firewall device + */ List listByFirewallDeviceId(long lbDeviceId); } diff --git a/server/src/com/cloud/network/dao/NetworkExternalLoadBalancerDao.java b/server/src/com/cloud/network/dao/NetworkExternalLoadBalancerDao.java index 8c8ede0331f..44debfed907 100644 --- a/server/src/com/cloud/network/dao/NetworkExternalLoadBalancerDao.java +++ b/server/src/com/cloud/network/dao/NetworkExternalLoadBalancerDao.java @@ -23,6 +23,18 @@ import com.cloud.network.NetworkExternalLoadBalancerVO; import com.cloud.utils.db.GenericDao; public interface NetworkExternalLoadBalancerDao extends GenericDao { + + /** + * find the network to load balancer device mapping corresponding to a network + * @param networkId guest network Id + * @return return NetworkExternalLoadBalancerVO for the guest network + */ NetworkExternalLoadBalancerVO findByNetworkId(long networkId); - List listByLBDeviceId(long lbDeviceId); + + /** + * list all network to load balancer device mappings corresponding to a load balancer device Id + * @param lbDeviceId load balancer device Id + * @return list of NetworkExternalLoadBalancerVO mappings corresponding to the networks mapped to the load balancer device + */ + List listByLoadBalancerDeviceId(long lbDeviceId); } diff --git a/server/src/com/cloud/network/dao/NetworkExternalLoadBalancerDaoImpl.java b/server/src/com/cloud/network/dao/NetworkExternalLoadBalancerDaoImpl.java index a4539193ae2..8998f4337a1 100644 --- a/server/src/com/cloud/network/dao/NetworkExternalLoadBalancerDaoImpl.java +++ b/server/src/com/cloud/network/dao/NetworkExternalLoadBalancerDaoImpl.java @@ -53,7 +53,7 @@ public class NetworkExternalLoadBalancerDaoImpl extends GenericDaoBase listByLBDeviceId(long lbDeviceId) { + public List listByLoadBalancerDeviceId(long lbDeviceId) { SearchCriteria sc = deviceIdSearch.create(); sc.setParameters("externalLBDeviceId", lbDeviceId); return search(sc, null); diff --git a/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java b/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java index 72779d4a783..dda14b3195d 100644 --- a/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java @@ -19,23 +19,36 @@ package com.cloud.network.element; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.ejb.Local; - import org.apache.log4j.Logger; +import com.cloud.api.commands.AddExternalLoadBalancerCmd; +import com.cloud.api.commands.DeleteExternalLoadBalancerCmd; +import com.cloud.api.commands.ListExternalLoadBalancersCmd; import com.cloud.configuration.ConfigurationManager; 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.network.ExternalNetworkDeviceManager; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.network.ExternalLoadBalancerDeviceManager; +import com.cloud.network.ExternalLoadBalancerDeviceManagerImpl; +import com.cloud.network.ExternalLoadBalancerDeviceVO; import com.cloud.network.Network; +import com.cloud.network.PhysicalNetworkVO; +import com.cloud.network.ExternalNetworkDeviceManager.NetworkDevice; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; @@ -43,25 +56,31 @@ import com.cloud.network.NetworkManager; import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetworkServiceProvider; 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.offering.NetworkOffering; -import com.cloud.utils.component.AdapterBase; +import com.cloud.resource.ServerResource; +import com.cloud.server.api.response.ExternalLoadBalancerResponse; import com.cloud.utils.component.Inject; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; +@SuppressWarnings("deprecation") @Local(value=NetworkElement.class) -public class F5ExternalLoadBalancerElement extends AdapterBase implements LoadBalancingServiceProvider { +public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceManagerImpl implements LoadBalancingServiceProvider, F5ExternalLoadBalancerElementService, ExternalLoadBalancerDeviceManager { private static final Logger s_logger = Logger.getLogger(F5ExternalLoadBalancerElement.class); @Inject NetworkManager _networkManager; - @Inject ExternalNetworkDeviceManager _externalNetworkManager; @Inject ConfigurationManager _configMgr; @Inject NetworkServiceMapDao _ntwkSrvcDao; - + @Inject DataCenterDao _dcDao; + @Inject PhysicalNetworkDao _physicalNetworkDao; + @Inject HostDao _hostDao; + private boolean canHandle(Network config) { DataCenter zone = _configMgr.getZone(config.getDataCenterId()); if (config.getGuestType() != Network.GuestType.Isolated || config.getTrafficType() != TrafficType.Guest) { @@ -81,7 +100,7 @@ public class F5ExternalLoadBalancerElement extends AdapterBase implements LoadBa } try { - return _externalNetworkManager.manageGuestNetworkWithExternalLoadBalancer(true, guestConfig); + return manageGuestNetworkWithExternalLoadBalancer(true, guestConfig); } catch (InsufficientCapacityException capacityException) { // TODO: handle out of capacity exception return false; @@ -105,7 +124,7 @@ public class F5ExternalLoadBalancerElement extends AdapterBase implements LoadBa } try { - return _externalNetworkManager.manageGuestNetworkWithExternalLoadBalancer(false, guestConfig); + return manageGuestNetworkWithExternalLoadBalancer(false, guestConfig); } catch (InsufficientCapacityException capacityException) { // TODO: handle out of capacity exception return false; @@ -123,7 +142,7 @@ public class F5ExternalLoadBalancerElement extends AdapterBase implements LoadBa return false; } - return _externalNetworkManager.applyLoadBalancerRules(config, rules); + return applyLoadBalancerRules(config, rules); } @Override @@ -175,5 +194,77 @@ public class F5ExternalLoadBalancerElement extends AdapterBase implements LoadBa 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 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 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 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); + } } diff --git a/server/src/com/cloud/network/element/F5ExternalLoadBalancerElementService.java b/server/src/com/cloud/network/element/F5ExternalLoadBalancerElementService.java new file mode 100644 index 00000000000..b95c1e50117 --- /dev/null +++ b/server/src/com/cloud/network/element/F5ExternalLoadBalancerElementService.java @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.network.element; + +import java.util.List; + +import com.cloud.api.commands.AddExternalLoadBalancerCmd; +import com.cloud.api.commands.DeleteExternalLoadBalancerCmd; +import com.cloud.api.commands.ListExternalLoadBalancersCmd; +import com.cloud.host.Host; +import com.cloud.server.api.response.ExternalLoadBalancerResponse; +import com.cloud.utils.component.PluggableService; + +@SuppressWarnings("deprecation") +public interface F5ExternalLoadBalancerElementService extends PluggableService { + + @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 listExternalLoadBalancers(ListExternalLoadBalancersCmd cmd); + + @Deprecated // API helper function supported for backward compatibility + public ExternalLoadBalancerResponse createExternalLoadBalancerResponse(Host externalLb); +} diff --git a/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java b/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java index 41841c3ae01..d9e778c21f7 100644 --- a/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java +++ b/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java @@ -19,40 +19,50 @@ package com.cloud.network.element; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; - import javax.ejb.Local; - import org.apache.log4j.Logger; +import com.cloud.api.commands.AddExternalFirewallCmd; +import com.cloud.api.commands.DeleteExternalFirewallCmd; +import com.cloud.api.commands.ListExternalFirewallsCmd; import com.cloud.configuration.ConfigurationManager; import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenterVO; import com.cloud.dc.DataCenter.NetworkType; +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.dao.HostDao; -import com.cloud.network.ExternalNetworkDeviceManager; import com.cloud.network.Network; +import com.cloud.network.ExternalNetworkDeviceManager.NetworkDevice; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; +import com.cloud.network.ExternalFirewallDeviceManagerImpl; import com.cloud.network.NetworkManager; import com.cloud.network.PhysicalNetworkServiceProvider; +import com.cloud.network.PhysicalNetworkVO; import com.cloud.network.PublicIpAddress; import com.cloud.network.RemoteAccessVpn; import com.cloud.network.VpnUser; import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.PhysicalNetworkDao; +import com.cloud.network.resource.JuniperSrxResource; import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.PortForwardingRule; import com.cloud.offering.NetworkOffering; -import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; -import com.cloud.utils.component.AdapterBase; +import com.cloud.resource.ServerResource; +import com.cloud.server.api.response.ExternalFirewallResponse; import com.cloud.utils.component.Inject; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; @@ -60,19 +70,21 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; @Local(value=NetworkElement.class) -public class JuniperSRXExternalFirewallElement extends AdapterBase implements SourceNatServiceProvider, FirewallServiceProvider, PortForwardingServiceProvider, RemoteAccessVPNServiceProvider { +public class JuniperSRXExternalFirewallElement extends ExternalFirewallDeviceManagerImpl implements SourceNatServiceProvider, FirewallServiceProvider, + PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, JuniperSRXFirewallElementService{ private static final Logger s_logger = Logger.getLogger(JuniperSRXExternalFirewallElement.class); private static final Map> capabilities = setCapabilities(); @Inject NetworkManager _networkManager; - @Inject ExternalNetworkDeviceManager _externalNetworkManager; @Inject HostDao _hostDao; @Inject ConfigurationManager _configMgr; @Inject NetworkOfferingDao _networkOfferingDao; @Inject NetworkDao _networksDao; - + @Inject DataCenterDao _dcDao; + @Inject PhysicalNetworkDao _physicalNetworkDao; + private boolean canHandle(Network config) { DataCenter zone = _configMgr.getZone(config.getDataCenterId()); if ((zone.getNetworkType() == NetworkType.Advanced && config.getGuestType() != Network.GuestType.Isolated) || (zone.getNetworkType() == NetworkType.Basic && config.getGuestType() != Network.GuestType.Shared)) { @@ -98,7 +110,7 @@ public class JuniperSRXExternalFirewallElement extends AdapterBase implements So } try { - return _externalNetworkManager.manageGuestNetworkWithExternalFirewall(true, network); + return manageGuestNetworkWithExternalFirewall(true, network); } catch (InsufficientCapacityException capacityException) { // TODO: handle out of capacity exception return false; @@ -129,7 +141,7 @@ public class JuniperSRXExternalFirewallElement extends AdapterBase implements So return false; } try { - return _externalNetworkManager.manageGuestNetworkWithExternalFirewall(false, network); + return manageGuestNetworkWithExternalFirewall(false, network); } catch (InsufficientCapacityException capacityException) { // TODO: handle out of capacity exception return false; @@ -147,7 +159,7 @@ public class JuniperSRXExternalFirewallElement extends AdapterBase implements So return false; } - return _externalNetworkManager.applyIps(network, ipAddresses); + return applyIps(network, ipAddresses); } @@ -157,7 +169,7 @@ public class JuniperSRXExternalFirewallElement extends AdapterBase implements So return false; } - return _externalNetworkManager.applyFirewallRules(config, rules); + return applyFirewallRules(config, rules); } @Override @@ -166,7 +178,7 @@ public class JuniperSRXExternalFirewallElement extends AdapterBase implements So return false; } - return _externalNetworkManager.manageRemoteAccessVpn(true, config, vpn); + return manageRemoteAccessVpn(true, config, vpn); } @@ -176,7 +188,7 @@ public class JuniperSRXExternalFirewallElement extends AdapterBase implements So return false; } - return _externalNetworkManager.manageRemoteAccessVpn(false, config, vpn); + return manageRemoteAccessVpn(false, config, vpn); } @Override @@ -187,7 +199,7 @@ public class JuniperSRXExternalFirewallElement extends AdapterBase implements So return null; } - boolean result = _externalNetworkManager.manageRemoteAccessVpnUsers(config, vpn, users); + boolean result = manageRemoteAccessVpnUsers(config, vpn, users); String[] results = new String[users.size()]; for (int i = 0; i < results.length; i++) { results[i] = String.valueOf(result); @@ -249,7 +261,7 @@ public class JuniperSRXExternalFirewallElement extends AdapterBase implements So return false; } - return _externalNetworkManager.applyFirewallRules(network, rules); + return applyFirewallRules(network, rules); } @Override @@ -269,6 +281,67 @@ public class JuniperSRXExternalFirewallElement extends AdapterBase implements So public boolean canEnableIndividualServices() { return false; } -} + @Override + @Deprecated // should use more generic addNetworkDevice command to add firewall + public Host addExternalFirewall(AddExternalFirewallCmd cmd) { + Long zoneId = cmd.getZoneId(); + DataCenterVO zone =null; + PhysicalNetworkVO pNetwork=null; + zone = _dcDao.findById(zoneId); + if (zone == null) { + throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId); + } + + List 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.JuniperSRXFirewall.getName(); + return addExternalFirewall(pNetwork.getId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), deviceType, (ServerResource) new JuniperSrxResource()); + } + @Override + public boolean deleteExternalFirewall(DeleteExternalFirewallCmd cmd) { + return deleteExternalFirewall(cmd.getId()); + } + + + @Override + @Deprecated // should use more generic listNetworkDevice command + public List listExternalFirewalls(ListExternalFirewallsCmd cmd) { + List firewallHosts = new ArrayList(); + 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 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); + } + + firewallHosts.addAll(listExternalFirewalls(pNetwork.getId(), NetworkDevice.JuniperSRXFirewall.getName())); + return firewallHosts; + } + + public ExternalFirewallResponse createExternalFirewallResponse(Host externalFirewall) { + return super.createExternalFirewallResponse(externalFirewall); + } + + @Override + public String getPropertiesFile() { + return "junipersrx_commands.properties"; + } +} \ No newline at end of file diff --git a/server/src/com/cloud/network/element/JuniperSRXFirewallElementService.java b/server/src/com/cloud/network/element/JuniperSRXFirewallElementService.java new file mode 100644 index 00000000000..11d425c4763 --- /dev/null +++ b/server/src/com/cloud/network/element/JuniperSRXFirewallElementService.java @@ -0,0 +1,25 @@ +package com.cloud.network.element; + +import java.util.List; + +import com.cloud.api.commands.AddExternalFirewallCmd; +import com.cloud.api.commands.DeleteExternalFirewallCmd; +import com.cloud.api.commands.ListExternalFirewallsCmd; +import com.cloud.host.Host; +import com.cloud.server.api.response.ExternalFirewallResponse; +import com.cloud.utils.component.PluggableService; + +public interface JuniperSRXFirewallElementService extends PluggableService { + + @Deprecated // API helper function supported for backward compatibility + public Host addExternalFirewall(AddExternalFirewallCmd cmd); + + @Deprecated // API helper function supported for backward compatibility + public boolean deleteExternalFirewall(DeleteExternalFirewallCmd cmd); + + @Deprecated // API helper function supported for backward compatibility + public List listExternalFirewalls(ListExternalFirewallsCmd cmd); + + @Deprecated // API helper function supported for backward compatibility + public ExternalFirewallResponse createExternalFirewallResponse(Host externalFirewall); +} diff --git a/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java b/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java index eeda45347cd..46322034fff 100644 --- a/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java @@ -19,49 +19,78 @@ package com.cloud.network.element; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; - import javax.ejb.Local; - import org.apache.log4j.Logger; +import com.cloud.agent.AgentManager; +import com.cloud.api.commands.AddNetscalerLoadBalancerCmd; +import com.cloud.api.commands.ConfigureNetscalerLoadBalancerCmd; +import com.cloud.api.commands.DeleteNetscalerLoadBalancerCmd; +import com.cloud.api.commands.ListNetscalerLoadBalancerNetworksCmd; +import com.cloud.api.commands.ListNetscalerLoadBalancersCmd; +import com.cloud.api.response.NetscalerLoadBalancerResponse; import com.cloud.configuration.ConfigurationManager; import com.cloud.dc.DataCenter; +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.network.ExternalNetworkDeviceManager; +import com.cloud.host.dao.HostDao; +import com.cloud.network.ExternalLoadBalancerDeviceManager; +import com.cloud.network.ExternalLoadBalancerDeviceManagerImpl; +import com.cloud.network.ExternalLoadBalancerDeviceVO; import com.cloud.network.Network; +import com.cloud.network.NetworkExternalLoadBalancerVO; +import com.cloud.network.NetworkVO; +import com.cloud.network.PhysicalNetworkVO; +import com.cloud.network.ExternalLoadBalancerDeviceVO.LBDeviceState; +import com.cloud.network.ExternalNetworkDeviceManager.NetworkDevice; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.NetworkManager; import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetworkServiceProvider; +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.NetscalerResource; import com.cloud.offering.NetworkOffering; -import com.cloud.utils.component.AdapterBase; +import com.cloud.resource.ServerResource; 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; @Local(value=NetworkElement.class) -public class NetscalerExternalLoadBalancerElement extends AdapterBase implements LoadBalancingServiceProvider { +public class NetscalerExternalLoadBalancerElement extends ExternalLoadBalancerDeviceManagerImpl implements LoadBalancingServiceProvider, NetscalerLoadBalancerElementService, ExternalLoadBalancerDeviceManager { private static final Logger s_logger = Logger.getLogger(NetscalerExternalLoadBalancerElement.class); - + @Inject NetworkManager _networkManager; - @Inject ExternalNetworkDeviceManager _externalNetworkManager; @Inject ConfigurationManager _configMgr; @Inject NetworkServiceMapDao _ntwkSrvcDao; - + @Inject AgentManager _agentMgr; + @Inject NetworkManager _networkMgr; + @Inject HostDao _hostDao; + @Inject DataCenterDao _dcDao; + @Inject ExternalLoadBalancerDeviceDao _lbDeviceDao; + @Inject NetworkExternalLoadBalancerDao _networkLBDao; + @Inject PhysicalNetworkDao _physicalNetworkDao; + @Inject NetworkDao _networkDao; + private boolean canHandle(Network config) { DataCenter zone = _configMgr.getZone(config.getDataCenterId()); if (config.getGuestType() != Network.GuestType.Isolated || config.getTrafficType() != TrafficType.Guest) { @@ -81,9 +110,9 @@ public class NetscalerExternalLoadBalancerElement extends AdapterBase implements } try { - return _externalNetworkManager.manageGuestNetworkWithExternalLoadBalancer(true, guestConfig); + return manageGuestNetworkWithExternalLoadBalancer(true, guestConfig); } catch (InsufficientCapacityException capacityException) { - // TODO: handle out of capacity exception + // TODO: handle out of capacity exception gracefully in case of multple providers available return false; } } @@ -105,27 +134,27 @@ public class NetscalerExternalLoadBalancerElement extends AdapterBase implements } try { - return _externalNetworkManager.manageGuestNetworkWithExternalLoadBalancer(false, guestConfig); + return manageGuestNetworkWithExternalLoadBalancer(false, guestConfig); } catch (InsufficientCapacityException capacityException) { - // TODO: handle out of capacity exception + // TODO: handle out of capacity exception gracefully in case of multple providers available return false; } } - + @Override public boolean destroy(Network config) { return true; } - + @Override public boolean applyLBRules(Network config, List rules) throws ResourceUnavailableException { if (!canHandle(config)) { return false; } - return _externalNetworkManager.applyLoadBalancerRules(config, rules); + return applyLoadBalancerRules(config, rules); } - + @Override public Map> getCapabilities() { Map> capabilities = new HashMap>(); @@ -152,7 +181,148 @@ public class NetscalerExternalLoadBalancerElement extends AdapterBase implements return capabilities; } - + + @Override + public ExternalLoadBalancerDeviceVO addNetscalerLoadBalancer(AddNetscalerLoadBalancerCmd cmd) { + String deviceName = cmd.getDeviceType(); + if (!isNetscalerDevice(deviceName)) { + throw new InvalidParameterValueException("Invalid Netscaler device type"); + } + + return addExternalLoadBalancer(cmd.getPhysicalNetworkId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), deviceName, (ServerResource) new NetscalerResource()); + } + + @Override + public boolean deleteNetscalerLoadBalancer(DeleteNetscalerLoadBalancerCmd cmd) { + Long lbDeviceId = cmd.getLoadBalancerDeviceId(); + + ExternalLoadBalancerDeviceVO lbDeviceVo = _lbDeviceDao.findById(lbDeviceId); + if ((lbDeviceVo == null) || !isNetscalerDevice(lbDeviceVo.getDeviceName())) { + throw new InvalidParameterValueException("No netscaler device found with ID: " + lbDeviceId); + } + + return deleteExternalLoadBalancer(lbDeviceVo.getHostId()); + } + + @Override + public ExternalLoadBalancerDeviceVO configureNetscalerLoadBalancer(ConfigureNetscalerLoadBalancerCmd cmd) { + Long lbDeviceId = cmd.getLoadBalancerDeviceId(); + Boolean dedicatedUse = cmd.getLoadBalancerDedicated(); + Long capacity = cmd.getLoadBalancerCapacity(); + + ExternalLoadBalancerDeviceVO lbDeviceVo = _lbDeviceDao.findById(lbDeviceId); + if ((lbDeviceVo == null) || !isNetscalerDevice(lbDeviceVo.getDeviceName())) { + throw new InvalidParameterValueException("No netscaler device found with ID: " + lbDeviceId); + } + + if (dedicatedUse != null || capacity != null) { + + String deviceName = lbDeviceVo.getDeviceName(); + if (NetworkDevice.NetscalerSDXLoadBalancer.getName().equalsIgnoreCase(deviceName)) { + // FIXME: how to interpret SDX device capacity + } else if (NetworkDevice.NetscalerMPXLoadBalancer.getName().equalsIgnoreCase(deviceName)) { + if (dedicatedUse != null && dedicatedUse == true) { + throw new InvalidParameterValueException("Netscaler MPX device should be shared and can not be dedicated to a single accoutnt."); + } + } + + // check if any networks are using this netscaler device + List 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 netscalr device than configured capacity"); + } + + if (dedicatedUse !=null && dedicatedUse == true) { + throw new CloudRuntimeException("There are networks already using this netscalr device to make device dedicated"); + } + } + + if (capacity != null) { + lbDeviceVo.setCapacity(capacity); + } + + if(dedicatedUse != null) { + lbDeviceVo.setIsDedicatedDevice(dedicatedUse); + } + } + + lbDeviceVo.setState(LBDeviceState.Enabled); + _lbDeviceDao.update(lbDeviceId, lbDeviceVo); + return lbDeviceVo; + } + + @Override + public String getPropertiesFile() { + return "netscalerloadbalancer_commands.properties"; + } + + @Override + public List listNetworks(ListNetscalerLoadBalancerNetworksCmd cmd) { + Long lbDeviceId = cmd.getLoadBalancerDeviceId(); + List networks = new ArrayList(); + + ExternalLoadBalancerDeviceVO lbDeviceVo = _lbDeviceDao.findById(lbDeviceId); + if (lbDeviceVo == null || !isNetscalerDevice(lbDeviceVo.getDeviceName())) { + throw new InvalidParameterValueException("Could not find Netscaler load balancer device with ID: " + lbDeviceId); + } + + List networkLbMaps = _networkLBDao.listByLoadBalancerDeviceId(lbDeviceId); + if (networkLbMaps != null && !networkLbMaps.isEmpty()) { + for (NetworkExternalLoadBalancerVO networkLbMap : networkLbMaps) { + NetworkVO network = _networkDao.findById(networkLbMap.getId()); + networks.add(network); + } + } + + return networks; + } + + @Override + public List listNetscalerLoadBalancers(ListNetscalerLoadBalancersCmd cmd) { + Long physcialNetworkId = cmd.getPhysicalNetworkId(); + Long lbDeviceId = cmd.getLoadBalancerDeviceId(); + PhysicalNetworkVO pNetwork = null; + List lbDevices = new ArrayList (); + + 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 || !isNetscalerDevice(lbDeviceVo.getDeviceName())) { + throw new InvalidParameterValueException("Could not find Netscaler 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.Netscaler.getName()); + return lbDevices; + } + + return null; + } + + @Override + public NetscalerLoadBalancerResponse createNetscalerLoadBalancerResponse(ExternalLoadBalancerDeviceVO lbDeviceVO) { + NetscalerLoadBalancerResponse response = new NetscalerLoadBalancerResponse(); + response.setId(lbDeviceVO.getId()); + response.setPhysicalNetworkId(lbDeviceVO.getPhysicalNetworkId()); + response.setDeviceName(lbDeviceVO.getDeviceName()); + response.setDeviceCapacity(lbDeviceVO.getCapacity()); + response.setDedicatedLoadBalancer(lbDeviceVO.getIsDedicatedDevice()); + response.setProvider(lbDeviceVO.getProviderName()); + response.setDeviceState(lbDeviceVO.getState().name()); + return response; + } + @Override public Provider getProvider() { return Provider.Netscaler; @@ -160,14 +330,23 @@ public class NetscalerExternalLoadBalancerElement extends AdapterBase implements @Override public boolean isReady(PhysicalNetworkServiceProvider provider) { - // FIXME: return true if atleast one Netscaler device is added in to physical network and is configured (in enabled state) - return true; + List lbDevices = _lbDeviceDao.listByPhysicalNetworkAndProvider(provider.getPhysicalNetworkId(), Provider.Netscaler.getName()); + + // true if at-least one Netscaler 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 + // TODO reset the configuration on all of the netscaler devices in this physical network return true; } @@ -175,4 +354,14 @@ public class NetscalerExternalLoadBalancerElement extends AdapterBase implements public boolean canEnableIndividualServices() { return false; } -} + + private boolean isNetscalerDevice(String deviceName) { + if ((deviceName == null) || ((!deviceName.equalsIgnoreCase(NetworkDevice.NetscalerMPXLoadBalancer.getName())) && + (!deviceName.equalsIgnoreCase(NetworkDevice.NetscalerSDXLoadBalancer.getName())) && + (!deviceName.equalsIgnoreCase(NetworkDevice.NetscalerVPXLoadBalancer.getName())))) { + return false; + } else { + return true; + } + } +} \ No newline at end of file diff --git a/server/src/com/cloud/network/element/NetscalerLoadBalancerElementService.java b/server/src/com/cloud/network/element/NetscalerLoadBalancerElementService.java new file mode 100644 index 00000000000..437baf19172 --- /dev/null +++ b/server/src/com/cloud/network/element/NetscalerLoadBalancerElementService.java @@ -0,0 +1,75 @@ +/** + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.network.element; + +import java.util.List; +import com.cloud.api.commands.AddNetscalerLoadBalancerCmd; +import com.cloud.api.commands.ConfigureNetscalerLoadBalancerCmd; +import com.cloud.api.commands.DeleteNetscalerLoadBalancerCmd; +import com.cloud.api.commands.ListNetscalerLoadBalancerNetworksCmd; +import com.cloud.api.commands.ListNetscalerLoadBalancersCmd; +import com.cloud.api.response.NetscalerLoadBalancerResponse; +import com.cloud.network.ExternalLoadBalancerDeviceVO; +import com.cloud.network.Network; +import com.cloud.utils.component.PluggableService; + +public interface NetscalerLoadBalancerElementService extends PluggableService { + + /** + * adds a Netscaler load balancer device in to a physical network + * @param AddNetscalerLoadBalancerCmd + * @return ExternalLoadBalancerDeviceVO object for the device added + */ + public ExternalLoadBalancerDeviceVO addNetscalerLoadBalancer(AddNetscalerLoadBalancerCmd cmd); + + /** + * removes a Netscaler load balancer device from a physical network + * @param DeleteNetscalerLoadBalancerCmd + * @return ExternalLoadBalancerDeviceVO object for the device deleted + */ + public boolean deleteNetscalerLoadBalancer(DeleteNetscalerLoadBalancerCmd cmd); + + /** + * configures a Netscaler load balancer device added in a physical network + * @param ConfigureNetscalerLoadBalancerCmd + * @return ExternalLoadBalancerDeviceVO for the device configured + */ + public ExternalLoadBalancerDeviceVO configureNetscalerLoadBalancer(ConfigureNetscalerLoadBalancerCmd cmd); + + /** + * lists all the load balancer devices added in to a physical network + * @param physicalNetworkId physical Network Id + * @return list of ExternalLoadBalancerDeviceVO for the devices in the physical network. + */ + public List listNetscalerLoadBalancers(ListNetscalerLoadBalancersCmd cmd); + + /** + * lists all the guest networks using a Netscaler load balancer device + * @param lbDeviceId external load balancer device Id + * @return list of the guest networks that are using this Netscaler load balancer + */ + public List listNetworks(ListNetscalerLoadBalancerNetworksCmd cmd); + + /** + * creates API response object for netscaler load balancers + * @param lbDeviceVO external load balancer VO object + * @return NetscalerLoadBalancerResponse + */ + public NetscalerLoadBalancerResponse createNetscalerLoadBalancerResponse(ExternalLoadBalancerDeviceVO lbDeviceVO); +} diff --git a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java index 74c21399476..7362550c073 100644 --- a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java @@ -23,6 +23,7 @@ import java.util.List; import javax.ejb.Local; +import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenter; import com.cloud.dc.dao.DataCenterDao; @@ -35,11 +36,13 @@ import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientVirtualNetworkCapcityException; import com.cloud.network.ExternalNetworkDeviceManager; import com.cloud.network.Network; +import com.cloud.network.PhysicalNetworkVO; import com.cloud.network.Network.State; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.ovs.OvsNetworkManager; import com.cloud.network.ovs.OvsTunnelManager; import com.cloud.network.rules.PortForwardingRuleVO; @@ -64,8 +67,6 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru { @Inject NetworkManager _networkMgr; @Inject - ExternalNetworkDeviceManager _externalNetworkMgr; - @Inject NetworkDao _networkDao; @Inject DataCenterDao _zoneDao; @@ -77,6 +78,7 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru { OvsNetworkManager _ovsNetworkMgr; @Inject OvsTunnelManager _tunnelMgr; + @Inject PhysicalNetworkDao _physicalNetworkDao; @Override public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) { @@ -129,12 +131,12 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru { } // Determine the offset from the lowest vlan tag - int offset = _externalNetworkMgr.getVlanOffset(config.getPhysicalNetworkId(), vlanTag); + int offset = getVlanOffset(config.getPhysicalNetworkId(), vlanTag); // Determine the new gateway and CIDR String[] oldCidr = config.getCidr().split("/"); String oldCidrAddress = oldCidr[0]; - int cidrSize = _externalNetworkMgr.getGloballyConfiguredCidrSize(); + int cidrSize = getGloballyConfiguredCidrSize(); // If the offset has more bits than there is room for, return null long bitsInOffset = 32 - Integer.numberOfLeadingZeros(offset); @@ -171,6 +173,29 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru { return implemented; } + public int getVlanOffset(long physicalNetworkId, int vlanTag) { + PhysicalNetworkVO pNetwork = _physicalNetworkDao.findById(physicalNetworkId); + if (pNetwork == null) { + throw new CloudRuntimeException("Could not find the physical Network " + physicalNetworkId + "."); + } + + if (pNetwork.getVnet() == null) { + throw new CloudRuntimeException("Could not find vlan range for physical Network " + physicalNetworkId + "."); + } + String vlanRange[] = pNetwork.getVnet().split("-"); + int lowestVlanTag = Integer.valueOf(vlanRange[0]); + return vlanTag - lowestVlanTag; + } + + public int getGloballyConfiguredCidrSize() { + try { + String globalVlanBits = _configDao.getValue(Config.GuestVlanBits.key()); + return 8 + Integer.parseInt(globalVlanBits); + } catch (Exception e) { + throw new CloudRuntimeException("Failed to read the globally configured VLAN bits size."); + } + } + @Override public NicProfile allocate(Network config, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { @@ -227,7 +252,7 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru { nic.setDns2(dc.getDns2()); nic.setNetmask(NetUtils.cidr2Netmask(config.getCidr())); long cidrAddress = NetUtils.ip2Long(config.getCidr().split("/")[0]); - int cidrSize = _externalNetworkMgr.getGloballyConfiguredCidrSize(); + int cidrSize = getGloballyConfiguredCidrSize(); nic.setGateway(config.getGateway()); if (nic.getIp4Address() == null) { diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 5e04bc071df..56b7d967621 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -1929,15 +1929,17 @@ CREATE TABLE `cloud`.`physical_network_service_providers` ( CREATE TABLE `cloud`.`external_load_balancer_devices` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', - `physical_network_id` bigint unsigned NOT NULL COMMENT 'id of the physical network in to which the device is added', - `provider_name` varchar(255) NOT NULL COMMENT 'Service Provider name corresponding to this device', + `uuid` varchar(255) UNIQUE, + `physical_network_id` bigint unsigned NOT NULL COMMENT 'id of the physical network in to which load balancer device is added', + `provider_name` varchar(255) NOT NULL COMMENT 'Service Provider name corresponding to this load balancer device', `device_name` varchar(255) NOT NULL COMMENT 'name of the load balancer device', - `state` varchar(32) NOT NULL DEFAULT 'Disabled' COMMENT 'state (enabled/disabled/shutdown) of the device', - `allocation_state` varchar(32) NOT NULL DEFAULT 'Free' COMMENT 'Allocation state of the device', - `managed` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if device is provisioned and its life cycle is managed by by cloudstack', - `host_id` bigint unsigned NOT NULL COMMENT 'host id coresponding to the external load balancer device', - `parent_host_id` bigint unsigned COMMENT 'if cloudstack managed, then host id on which this device is provisioned', `capacity` bigint unsigned NOT NULL DEFAULT 0 COMMENT 'Capacity of the load balancer device', + `state` varchar(32) NOT NULL DEFAULT 'Disabled' COMMENT 'state (enabled/disabled/shutdown) of the device', + `allocation_state` varchar(32) NOT NULL DEFAULT 'Free' COMMENT 'Allocation state (Free/Shared/Dedicated/Provider) of the device', + `is_dedicated` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if device/appliance meant for dedicated use only', + `is_managed` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if device/appliance is provisioned and its life cycle is managed by by cloudstack', + `host_id` bigint unsigned NOT NULL COMMENT 'host id coresponding to the external load balancer device', + `parent_host_id` bigint unsigned COMMENT 'if the device/appliance is cloudstack managed, then host id on which this device/appliance is provisioned', PRIMARY KEY (`id`), CONSTRAINT `fk_external_lb_devices_host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE, CONSTRAINT `fk_external_lb_devices_parent_host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE, @@ -1946,13 +1948,14 @@ CREATE TABLE `cloud`.`external_load_balancer_devices` ( CREATE TABLE `cloud`.`external_firewall_devices` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', - `host_id` bigint unsigned NOT NULL COMMENT 'host id coresponding to the external firewall device', - `physical_network_id` bigint unsigned NOT NULL COMMENT 'id of the physical network in to which the device is added', - `provider_name` varchar(255) NOT NULL COMMENT 'Service Provider name corresponding to this device', + `uuid` varchar(255) UNIQUE, + `physical_network_id` bigint unsigned NOT NULL COMMENT 'id of the physical network in to which firewall device is added', + `provider_name` varchar(255) NOT NULL COMMENT 'Service Provider name corresponding to this firewall device', + `device_name` varchar(255) NOT NULL COMMENT 'name of the firewall device', `state` varchar(32) NOT NULL DEFAULT 'Disabled' COMMENT 'state (enabled/disabled/shutdown) of the device', - `allocation_state` varchar(32) NOT NULL DEFAULT 'Free' COMMENT 'Allocation state of the device', + `allocation_state` varchar(32) NOT NULL DEFAULT 'Free' COMMENT 'Allocation state (Free/Allocated) of the device', + `host_id` bigint unsigned NOT NULL COMMENT 'host id coresponding to the external firewall device', `capacity` bigint unsigned NOT NULL DEFAULT 0 COMMENT 'Capacity of the external firewall device', - `capacity_type` varchar(32) NOT NULL DEFAULT 'Throughput' COMMENT 'Type of the capacity', PRIMARY KEY (`id`), CONSTRAINT `fk_external_firewall_devices__host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE, CONSTRAINT `fk_external_firewall_devices__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE @@ -1960,9 +1963,9 @@ CREATE TABLE `cloud`.`external_firewall_devices` ( CREATE TABLE `cloud`.`network_external_lb_device_map` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `uuid` varchar(255) UNIQUE, `network_id` bigint unsigned NOT NULL COMMENT ' guest network id', - `external_load_balancer_device_id` bigint unsigned NOT NULL COMMENT 'id of external LB device', - `subscribed_capacity` bigint unsigned NOT NULL DEFAULT 0 COMMENT 'Capacity of the device this network is subscrbed to', + `external_load_balancer_device_id` bigint unsigned NOT NULL COMMENT 'id of external load balancer device assigned for this network', `created` datetime COMMENT 'Date from when network started using the device', `removed` datetime COMMENT 'Date till the network stopped using the device ', PRIMARY KEY (`id`), @@ -1972,8 +1975,9 @@ CREATE TABLE `cloud`.`network_external_lb_device_map` ( CREATE TABLE `cloud`.`network_external_firewall_device_map` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `uuid` varchar(255) UNIQUE, `network_id` bigint unsigned NOT NULL COMMENT ' guest network id', - `external_firewall_device_id` bigint unsigned NOT NULL COMMENT 'id of external firewall device', + `external_firewall_device_id` bigint unsigned NOT NULL COMMENT 'id of external firewall device assigned for this device', `created` datetime COMMENT 'Date from when network started using the device', `removed` datetime COMMENT 'Date till the network stopped using the device ', PRIMARY KEY (`id`),