From adbd20ca5a00e563b9b991bf8fcf0a10c6989280 Mon Sep 17 00:00:00 2001 From: Edison Su Date: Wed, 23 Feb 2011 15:49:13 -0500 Subject: [PATCH] bug 8655: add security group for direct tagged network --- .../computing/LibvirtComputingResource.java | 32 +++---- api/src/com/cloud/api/ApiConstants.java | 1 + .../cloud/api/commands/CreateNetworkCmd.java | 8 ++ .../api/commands/CreateVlanIpRangeCmd.java | 3 +- .../com/cloud/api/commands/CreateZoneCmd.java | 8 ++ .../cloud/api/response/NetworkResponse.java | 11 +++ api/src/com/cloud/network/Network.java | 2 + scripts/vm/network/security_group.py | 83 +++++++------------ .../src/com/cloud/api/ApiResponseHelper.java | 2 + .../configuration/ConfigurationManager.java | 4 +- .../ConfigurationManagerImpl.java | 29 +++++-- .../src/com/cloud/network/NetworkManager.java | 4 +- .../com/cloud/network/NetworkManagerImpl.java | 22 ++++- server/src/com/cloud/network/NetworkVO.java | 15 +++- .../src/com/cloud/network/dao/NetworkDao.java | 1 + .../com/cloud/network/dao/NetworkDaoImpl.java | 15 ++++ .../cloud/network/guru/PublicNetworkGuru.java | 17 +++- .../VirtualNetworkApplianceManagerImpl.java | 4 +- .../security/SecurityGroupManagerImpl.java | 50 ++--------- .../cloud/server/ManagementServerImpl.java | 10 ++- server/src/com/cloud/vm/UserVmManager.java | 4 + .../src/com/cloud/vm/UserVmManagerImpl.java | 41 ++++++++- setup/db/create-schema.sql | 1 + setup/db/templates.sql | 2 +- 24 files changed, 237 insertions(+), 132 deletions(-) diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java index 48e66b1547b..9f90da879b7 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java @@ -1401,12 +1401,21 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } private Answer execute(SecurityIngressRulesCmd cmd) { + String vif = null; + try { + Connect conn = LibvirtConnection.getConnection(); + List nics = getInterfaces(conn, cmd.getVmName()); + vif = nics.get(0).getBrName(); + } catch (LibvirtException e) { + + } + boolean result = add_network_rules(cmd.getVmName(), Long.toString(cmd.getVmId()), cmd.getGuestIp(),cmd.getSignature(), Long.toString(cmd.getSeqNum()), cmd.getGuestMac(), - cmd.stringifyRules()); + cmd.stringifyRules(), vif); if (!result) { s_logger.warn("Failed to program network rules for vm " + cmd.getVmName()); @@ -2046,23 +2055,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv if (vmSpec.getType() != VirtualMachine.Type.User) { default_network_rules_for_systemvm(vmName); - } else { - NicTO[] nics = vmSpec.getNics(); - List vifs = getInterfaces(conn, vmName); - StringBuilder rules = new StringBuilder(); - - for (NicTO nic : nics) { - if (nic.getIsolationUri() != null ) { - if (nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString()) || - nic.getType() == TrafficType.Public) { - rules.append(nic.getIp() + "," + nic.getMac() + "," + vifs.get(nic.getDeviceId()).getDevName() + ";") ; - } - } - } - - if (rules.toString() != null) - default_network_rules(vmName, vmSpec.getId(), rules.toString()); - } + } // Attach each data volume to the VM, if there is a deferred attached disk for (DiskDef disk : vm.getDevices().getDisks()) { @@ -3179,7 +3172,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return true; } - private boolean add_network_rules(String vmName, String vmId, String guestIP, String sig, String seq, String mac, String rules) { + private boolean add_network_rules(String vmName, String vmId, String guestIP, String sig, String seq, String mac, String rules, String vif) { if (!_can_bridge_firewall) { return false; } @@ -3192,6 +3185,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv cmd.add("--sig", sig); cmd.add("--seq", seq); cmd.add("--vmmac", mac); + cmd.add("--vif", vif); if (rules != null) cmd.add("--rules", newRules); String result = cmd.execute(); diff --git a/api/src/com/cloud/api/ApiConstants.java b/api/src/com/cloud/api/ApiConstants.java index d94b2d12b2a..6e860582ad9 100755 --- a/api/src/com/cloud/api/ApiConstants.java +++ b/api/src/com/cloud/api/ApiConstants.java @@ -138,6 +138,7 @@ public class ApiConstants { public static final String SECURITY_GROUP_IDS = "securitygroupids"; public static final String SECURITY_GROUP_NAME = "securitygroupname"; public static final String SECURITY_GROUP_ID = "securitygroupid"; + public static final String SECURITY_GROUP_EANBLED = "securitygroupEnabled"; public static final String SENT = "sent"; public static final String SENT_BYTES = "sentbytes"; public static final String SERVICE_OFFERING_ID = "serviceofferingid"; diff --git a/api/src/com/cloud/api/commands/CreateNetworkCmd.java b/api/src/com/cloud/api/commands/CreateNetworkCmd.java index 5abc7621a18..80a9bd5760c 100644 --- a/api/src/com/cloud/api/commands/CreateNetworkCmd.java +++ b/api/src/com/cloud/api/commands/CreateNetworkCmd.java @@ -25,6 +25,7 @@ import com.cloud.api.BaseCmd; import com.cloud.api.Implementation; import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; +import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.response.NetworkResponse; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -81,6 +82,9 @@ public class CreateNetworkCmd extends BaseCmd { @Parameter(name=ApiConstants.NETWORK_DOMAIN, type=CommandType.STRING, description="network domain") private String networkDomain; + + @Parameter(name=ApiConstants.SECURITY_GROUP_EANBLED, type=CommandType.BOOLEAN, description="true if network is security group enabled, false otherwise") + private Boolean is_security_group_enabled; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -140,6 +144,10 @@ public class CreateNetworkCmd extends BaseCmd { public String getNetworkDomain() { return networkDomain; } + + public boolean isSecurityGroupEnabled() { + return is_security_group_enabled == null ? false : true; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/com/cloud/api/commands/CreateVlanIpRangeCmd.java b/api/src/com/cloud/api/commands/CreateVlanIpRangeCmd.java index 66300fa072b..5c4ce219964 100644 --- a/api/src/com/cloud/api/commands/CreateVlanIpRangeCmd.java +++ b/api/src/com/cloud/api/commands/CreateVlanIpRangeCmd.java @@ -91,7 +91,8 @@ public class CreateVlanIpRangeCmd extends BaseCmd { } public Boolean isForVirtualNetwork() { - return forVirtualNetwork == null ? true : forVirtualNetwork; + return false; + //return forVirtualNetwork == null ? true : forVirtualNetwork; } public String getGateway() { diff --git a/api/src/com/cloud/api/commands/CreateZoneCmd.java b/api/src/com/cloud/api/commands/CreateZoneCmd.java index 65812c7cab5..0f426e1f56b 100644 --- a/api/src/com/cloud/api/commands/CreateZoneCmd.java +++ b/api/src/com/cloud/api/commands/CreateZoneCmd.java @@ -67,6 +67,9 @@ public class CreateZoneCmd extends BaseCmd { @Parameter(name=ApiConstants.NETWORK_TYPE, type=CommandType.STRING, required=true, description="network type of the zone, can be Basic or Advanced") private String networkType; + + @Parameter(name=ApiConstants.SECURITY_GROUP_EANBLED, type=CommandType.BOOLEAN, description="true if network is security group enabled, false otherwise") + private Boolean is_security_group_enabled; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -112,6 +115,11 @@ public class CreateZoneCmd extends BaseCmd { return networkType; } + public boolean isSecurityGroupEnabled() { + return true; + //return is_security_group_enabled == null ? false : true; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// diff --git a/api/src/com/cloud/api/response/NetworkResponse.java b/api/src/com/cloud/api/response/NetworkResponse.java index 216cda3721a..83b8222213c 100644 --- a/api/src/com/cloud/api/response/NetworkResponse.java +++ b/api/src/com/cloud/api/response/NetworkResponse.java @@ -95,6 +95,9 @@ public class NetworkResponse extends BaseResponse{ @SerializedName("networkdomain") @Param(description="the network domain") private String networkDomain; + @SerializedName(ApiConstants.SECURITY_GROUP_EANBLED) @Param(description="true if security group is enabled, false otherwise") + private Boolean isSecurityGroupEnabled; + public Long getId() { return id; } @@ -327,4 +330,12 @@ public class NetworkResponse extends BaseResponse{ this.networkDomain = networkDomain; } + public Boolean getIsSecurityGroupEnabled() { + return this.isSecurityGroupEnabled; + } + + public void setIsSecurityGroupEnabled(Boolean sgEnabled) { + this.isSecurityGroupEnabled = sgEnabled; + } + } diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index 419be69a243..3af47467616 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -205,4 +205,6 @@ public interface Network extends ControlledEntity { String getNetworkDomain(); + boolean isSecurityGroupEnabled(); + } diff --git a/scripts/vm/network/security_group.py b/scripts/vm/network/security_group.py index df7c1c64926..81f3e5a4e0a 100755 --- a/scripts/vm/network/security_group.py +++ b/scripts/vm/network/security_group.py @@ -54,6 +54,7 @@ def can_bridge_firewall(privnic): print "failed to turn on bridge netfilter" exit(3) +''' try: execute("iptables -N BRIDGE-FIREWALL") execute("iptables -N BRIDGE-FIREWALL") @@ -72,10 +73,8 @@ def can_bridge_firewall(privnic): execute("iptables -A FORWARD -j DROP") except: result = 1 +''' - - if result == 1: - print "br firewall is not supported" if not os.path.exists('/var/run/cloud'): os.makedirs('/var/run/cloud') @@ -155,10 +154,9 @@ def destroy_ebtables_rules(vm_name): except: logging.debug("Ignoring failure to delete ebtables chain for vm " + vm_name) -def default_ebtables_rules(vm_name, rules): +def default_ebtables_rules(vm_name, vm_ip, vm_mac, vif): vmchain_in = vm_name + "-in" vmchain_out = vm_name + "-out" - rule = rules.split(";")[:-1] for chain in [vmchain_in, vmchain_out]: try: @@ -168,40 +166,30 @@ def default_ebtables_rules(vm_name, rules): try: # -s ! 52:54:0:56:44:32 -j DROP - for r in rule: - vif = r.split(",")[2] - execute("ebtables -t nat -A PREROUTING -i " + vif + " -j " + vmchain_in) - execute("ebtables -t nat -A POSTROUTING -o " + vif + " -j " + vmchain_out) + execute("ebtables -t nat -A PREROUTING -i " + vif + " -j " + vmchain_in) + execute("ebtables -t nat -A POSTROUTING -o " + vif + " -j " + vmchain_out) except: logging.debug("Failed to program default rules") return 'false' try: - for r in rule: - vm_ip = r.split(",")[0] - vm_mac = r.split(",")[1] - vif = r.split(",")[2] - execute("ebtables -t nat -A " + vmchain_in + " -i " + vif + " -s ! " + vm_mac + " -j DROP") - execute("ebtables -t nat -A " + vmchain_in + " -i " + vif + " -p ARP -s ! " + vm_mac + " -j DROP") - execute("ebtables -t nat -A " + vmchain_in + " -i " + vif + " -p ARP --arp-mac-src ! " + vm_mac + " -j DROP") - execute("ebtables -t nat -A " + vmchain_in + " -i " + vif + " -p ARP --arp-ip-src ! " + vm_ip + " -j DROP") - execute("ebtables -t nat -A " + vmchain_in + " -i " + vif + " -p ARP --arp-op Request -j ACCEPT") - execute("ebtables -t nat -A " + vmchain_in + " -i " + vif + " -p ARP --arp-op Reply -j ACCEPT") - execute("ebtables -t nat -A " + vmchain_in + " -i " + vif + " -p ARP -j DROP") + execute("ebtables -t nat -A " + vmchain_in + " -s ! " + vm_mac + " -j DROP") + execute("ebtables -t nat -A " + vmchain_in + " -p ARP -s ! " + vm_mac + " -j DROP") + execute("ebtables -t nat -A " + vmchain_in + " -p ARP --arp-mac-src ! " + vm_mac + " -j DROP") + execute("ebtables -t nat -A " + vmchain_in + " -p ARP --arp-ip-src ! " + vm_ip + " -j DROP") + execute("ebtables -t nat -A " + vmchain_in + " -p ARP --arp-op Request -j ACCEPT") + execute("ebtables -t nat -A " + vmchain_in + " -p ARP --arp-op Reply -j ACCEPT") + execute("ebtables -t nat -A " + vmchain_in + " -p ARP -j DROP") except: logging.exception("Failed to program default ebtables IN rules") return 'false' try: - for r in rule: - vm_ip = r.split(",")[0] - vm_mac = r.split(",")[1] - vif = r.split(",")[2] - execute("ebtables -t nat -A " + vmchain_out + " -i " + vif + " -p ARP --arp-op Reply --arp-mac-dst ! " + vm_mac + " -j DROP") - execute("ebtables -t nat -A " + vmchain_out + " -i " + vif + " -p ARP --arp-ip-dst ! " + vm_ip + " -j DROP") - execute("ebtables -t nat -A " + vmchain_out + " -i " + vif + " -p ARP --arp-op Request -j ACCEPT") - execute("ebtables -t nat -A " + vmchain_out + " -i " + vif + " -p ARP --arp-op Reply -j ACCEPT") - execute("ebtables -t nat -A " + vmchain_out + " -i " + vif + " -p ARP -j DROP") + execute("ebtables -t nat -A " + vmchain_out + " -p ARP --arp-op Reply --arp-mac-dst ! " + vm_mac + " -j DROP") + execute("ebtables -t nat -A " + vmchain_out + " -p ARP --arp-ip-dst ! " + vm_ip + " -j DROP") + execute("ebtables -t nat -A " + vmchain_out + " -p ARP --arp-op Request -j ACCEPT") + execute("ebtables -t nat -A " + vmchain_out + " -p ARP --arp-op Reply -j ACCEPT") + execute("ebtables -t nat -A " + vmchain_out + " -p ARP -j DROP") except: logging.debug("Failed to program default ebtables OUT rules") return 'false' @@ -235,7 +223,7 @@ def default_network_rules_systemvm(vm_name): return 'true' -def default_network_rules(vm_name, vm_id, rules): +def default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif): vmName = vm_name domID = getvmId(vm_name) delete_rules_for_vm_in_bridge_firewall_chain(vmName) @@ -254,35 +242,25 @@ def default_network_rules(vm_name, vm_id, rules): except: execute("iptables -F " + vmchain_default) - rule = rules.split(";")[:-1] try: - for r in rule: - vif = r.split(",")[2] - execute("iptables -A BRIDGE-FIREWALL -m physdev --physdev-is-bridged --physdev-out " + vif + " -j " + vmchain_default) - execute("iptables -A BRIDGE-FIREWALL -m physdev --physdev-is-bridged --physdev-in " + vif + " -j " + vmchain_default) + execute("iptables -A BRIDGE-FIREWALL -m physdev --physdev-is-bridged --physdev-out " + vif + " -j " + vmchain_default) + execute("iptables -A BRIDGE-FIREWALL -m physdev --physdev-is-bridged --physdev-in " + vif + " -j " + vmchain_default) execute("iptables -A " + vmchain_default + " -m state --state RELATED,ESTABLISHED -j ACCEPT") #allow dhcp - for r in rule: - vif = r.split(",")[2] - execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -p udp --dport 67 --sport 68 -j ACCEPT") - execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-out " + vif + " -p udp --dport 68 --sport 67 -j ACCEPT") + execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -p udp --dport 67 --sport 68 -j ACCEPT") + execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-out " + vif + " -p udp --dport 68 --sport 67 -j ACCEPT") #don't let vm spoof its ip address - for r in rule: - vmip = r.split(",")[0] - vif = r.split(",")[2] - execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " --source " + vmip + " -j ACCEPT") + execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " --source " + vm_ip + " -j ACCEPT") execute("iptables -A " + vmchain_default + " -j " + vmchain) except: logging.debug("Failed to program default rules for vm " + vm_name) return 'false' - default_ebtables_rules(vmchain, rules) + default_ebtables_rules(vmchain, vm_ip, vm_mac, vif) - for r in rule: - vm_ip = r.split(",")[0] - if write_rule_log_for_vm(vmName, vm_id, vm_ip, domID, '_initial_', '-1') == False: - logging.debug("Failed to log default network rules, ignoring") + if write_rule_log_for_vm(vmName, vm_id, vm_ip, domID, '_initial_', '-1') == False: + logging.debug("Failed to log default network rules, ignoring") logging.debug("Programmed default rules for vm " + vm_name) return 'true' @@ -441,7 +419,7 @@ def remove_rule_log_for_vm(vmName): return result -def add_network_rules(vm_name, vm_id, vm_ip, signature, seqno, vmMac, rules): +def add_network_rules(vm_name, vm_id, vm_ip, signature, seqno, vmMac, rules, vif): try: vmName = vm_name domId = getvmId(vmName) @@ -458,6 +436,9 @@ def add_network_rules(vm_name, vm_id, vm_ip, signature, seqno, vmMac, rules): write_rule_log_for_vm(vmName, vm_id, vm_ip, domId, signature, seqno) return 'true' + if changes[0] or changes[2]: + default_network_rules(vmName, vm_id, vm_ip, vmMac, vif) + lines = rules.split(';')[:-1] logging.debug(" programming network rules for IP: " + vm_ip + " vmname=" + vm_name) @@ -549,7 +530,7 @@ if __name__ == '__main__': if cmd == "can_bridge_firewall": can_bridge_firewall(args[1]) elif cmd == "default_network_rules": - default_network_rules(option.vmName, option.vmID, option.rules) + default_network_rules(option.vmName, option.vmID, option.vmIP, option.vmMAC, option.vif) elif cmd == "destroy_network_rules_for_vm": destroy_network_rules_for_vm(option.vmName) elif cmd == "default_network_rules_systemvm": @@ -557,6 +538,6 @@ if __name__ == '__main__': elif cmd == "get_rule_logs_for_vms": get_rule_logs_for_vms() elif cmd == "add_network_rules": - add_network_rules(option.vmName, option.vmID, option.vmIP, option.sig, option.seq, option.vmMAC, option.rules) + add_network_rules(option.vmName, option.vmID, option.vmIP, option.sig, option.seq, option.vmMAC, option.rules, option.vif) elif cmd == "cleanup_rules": cleanup_rules() diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index bea2a50d32f..7ccd8a130ac 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -2301,6 +2301,8 @@ public class ApiResponseHelper implements ResponseGenerator { response.setDns1(profile.getDns1()); response.setDns2(profile.getDns2()); + response.setIsSecurityGroupEnabled(network.isSecurityGroupEnabled()); + //populate capability Map> serviceCapabilitiesMap = ApiDBUtils.getNetworkCapabilities(network.getId()); List serviceResponses = new ArrayList(); diff --git a/server/src/com/cloud/configuration/ConfigurationManager.java b/server/src/com/cloud/configuration/ConfigurationManager.java index db4561b5e8c..ee0b4b429a8 100644 --- a/server/src/com/cloud/configuration/ConfigurationManager.java +++ b/server/src/com/cloud/configuration/ConfigurationManager.java @@ -112,7 +112,7 @@ public interface ConfigurationManager extends ConfigurationService, Manager { * @throws * @throws */ - DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, String vnetRange, String guestCidr, String domain, Long domainId, NetworkType zoneType); + DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, String vnetRange, String guestCidr, String domain, Long domainId, NetworkType zoneType, boolean isSecurityGroupEnabled); /** * Deletes a VLAN from the database, along with all of its IP addresses. Will not delete VLANs that have allocated IP addresses. @@ -173,7 +173,7 @@ public interface ConfigurationManager extends ConfigurationService, Manager { Vlan createVlanAndPublicIpRange(Long userId, Long zoneId, Long podId, String startIP, String endIP, String vlanGateway, String vlanNetmask, boolean forVirtualNetwork, String vlanId, Account account, Long networkId) throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException; - void createDefaultNetworks(long zoneId) throws ConcurrentOperationException; + void createDefaultNetworks(long zoneId, boolean isSecurityGroupEnabled) throws ConcurrentOperationException; DataCenterVO getZone(long id); diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index af28093dc51..77704a203aa 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1091,7 +1091,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } @Override @DB - public DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, String vnetRange, String guestCidr, String domain, Long domainId, NetworkType zoneType) { + public DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, String vnetRange, String guestCidr, String domain, Long domainId, NetworkType zoneType, boolean isSecurityGroupEnabled) { int vnetStart = 0; int vnetEnd = 0; if (vnetRange != null) { @@ -1134,8 +1134,11 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } //Create deafult networks - createDefaultNetworks(zone.getId()); + createDefaultNetworks(zone.getId(), isSecurityGroupEnabled); + if (isSecurityGroupEnabled) { + _configDao.update(Config.DirectAttachSecurityGroupsEnabled.key(), "true"); + } txn.commit(); return zone; } catch (Exception ex) { @@ -1148,7 +1151,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } @Override - public void createDefaultNetworks(long zoneId) throws ConcurrentOperationException{ + public void createDefaultNetworks(long zoneId, boolean isSecurityGroupEnabled) throws ConcurrentOperationException{ DataCenterVO zone = _zoneDao.findById(zoneId); //Create public, management, control and storage networks as a part of the zone creation if (zone != null) { @@ -1168,6 +1171,10 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura broadcastDomainType = BroadcastDomainType.LinkLocal; } else if (offering.getTrafficType() == TrafficType.Public) { if (zone.getNetworkType() == NetworkType.Advanced) { + if (isSecurityGroupEnabled) { + isNetworkDefault = true; + userNetwork.setSecurityGroupEnabled(isSecurityGroupEnabled); + } broadcastDomainType = BroadcastDomainType.Vlan; } else { continue; @@ -1176,6 +1183,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura if (zone.getNetworkType() == NetworkType.Basic) { isNetworkDefault = true; broadcastDomainType = BroadcastDomainType.Native; + userNetwork.setSecurityGroupEnabled(isSecurityGroupEnabled); } else { continue; } @@ -1233,7 +1241,12 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura vnetRange = null; } - return createZone(userId, zoneName, dns1, dns2, internalDns1, internalDns2, vnetRange, guestCidr, domainVO != null ? domainVO.getName() : null, domainId, zoneType); + boolean securityGroupEnabled = cmd.isSecurityGroupEnabled(); + if (zoneType == NetworkType.Basic) { + securityGroupEnabled = true; + } + + return createZone(userId, zoneName, dns1, dns2, internalDns1, internalDns2, vnetRange, guestCidr, domainVO != null ? domainVO.getName() : null, domainId, zoneType, securityGroupEnabled); } @Override @@ -1588,7 +1601,11 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura if (zone.getNetworkType() == DataCenter.NetworkType.Basic) { networkId = _networkMgr.getSystemNetworkByZoneAndTrafficType(zoneId, TrafficType.Guest).getId(); } else { - throw new InvalidParameterValueException("Nework id is required for Direct vlan creation "); + network = _networkMgr.getNetworkWithSecurityGroupEnabled(zoneId); + if (network == null) { + throw new InvalidParameterValueException("Nework id is required for Direct vlan creation "); + } + networkId = network.getId(); } } else if (network.getGuestType() == null || network.getGuestType() == GuestIpType.Virtual) { throw new InvalidParameterValueException("Can't create direct vlan for network id=" + networkId + " with GuestType: " + network.getGuestType()); @@ -1600,7 +1617,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura endIP = startIP; } - if (forVirtualNetwork || zone.getNetworkType() == DataCenter.NetworkType.Basic) { + if (forVirtualNetwork || zone.getNetworkType() == DataCenter.NetworkType.Basic || network.isSecurityGroupEnabled()) { if (vlanGateway == null || vlanNetmask == null || zoneId == null) { throw new InvalidParameterValueException("Gateway, netmask and zoneId have to be passed in for virtual and direct untagged networks"); } diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index a11c9865479..0dc5b55e40b 100644 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -142,7 +142,7 @@ public interface NetworkManager extends NetworkService { boolean destroyNetwork(long networkId, ReservationContext context); - Network createNetwork(long networkOfferingId, String name, String displayText, Boolean isShared, Boolean isDefault, Long zoneId, String gateway, String cidr, String vlanId, String networkDomain, Account owner) throws ConcurrentOperationException, InsufficientCapacityException; + Network createNetwork(long networkOfferingId, String name, String displayText, Boolean isShared, Boolean isDefault, Long zoneId, String gateway, String cidr, String vlanId, String networkDomain, Account owner, boolean isSecurityGroupEnabled) throws ConcurrentOperationException, InsufficientCapacityException; /** * @throws InsufficientCapacityException @@ -179,4 +179,6 @@ public interface NetworkManager extends NetworkService { boolean isServiceSupported(long networkId, Network.Service service); + Network getNetworkWithSecurityGroupEnabled(Long zoneId); + } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index c8155804b60..8f94fb035d4 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -871,7 +871,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag related = id; } - NetworkVO vo = new NetworkVO(id, config, offering.getId(), plan.getDataCenterId(), guru.getName(), owner.getDomainId(), owner.getId(), related, name, displayText, isShared, isDefault); + NetworkVO vo = new NetworkVO(id, config, offering.getId(), plan.getDataCenterId(), guru.getName(), owner.getDomainId(), owner.getId(), related, name, displayText, isShared, isDefault, predefined.isSecurityGroupEnabled()); configs.add(_networksDao.persist(vo, vo.getGuestType() != null)); } @@ -1502,7 +1502,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } txn.start(); - Network network = createNetwork(networkOfferingId, name, displayText, isShared, isDefault, zoneId, gateway, cidr, vlanId, networkDomain, owner); + Network network = createNetwork(networkOfferingId, name, displayText, isShared, isDefault, zoneId, gateway, cidr, vlanId, networkDomain, owner, cmd.isSecurityGroupEnabled()); // Don't pass owner to create vlan when network offering is of type Direct - done to prevent accountVlanMap entry // creation when vlan is mapped to network @@ -1521,7 +1521,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } @Override @DB - public Network createNetwork(long networkOfferingId, String name, String displayText, Boolean isShared, Boolean isDefault, Long zoneId, String gateway, String cidr, String vlanId, String networkDomain, Account owner) + public Network createNetwork(long networkOfferingId, String name, String displayText, Boolean isShared, Boolean isDefault, Long zoneId, String gateway, String cidr, String vlanId, String networkDomain, Account owner, boolean isSecurityGroupEnabled) throws ConcurrentOperationException, InsufficientCapacityException { Account ctxAccount = UserContext.current().getCaller(); Long userId = UserContext.current().getCallerUserId(); @@ -1535,6 +1535,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag DataCenterDeployment plan = new DataCenterDeployment(zoneId, null, null, null); NetworkVO userNetwork = new NetworkVO(); userNetwork.setNetworkDomain(networkDomain); + userNetwork.setSecurityGroupEnabled(isSecurityGroupEnabled); // cidr should be set only when the user is admin if (ctxAccount.getType() == Account.ACCOUNT_TYPE_ADMIN) { @@ -2142,6 +2143,19 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } return networks.get(0); } + + @Override + public Network getNetworkWithSecurityGroupEnabled(Long zoneId) { + List networks = _networksDao.listByZoneSecurityGroup(zoneId); + if (networks == null || networks.isEmpty()) { + return null; + } + + if (networks.size() > 1) { + s_logger.debug("There are multiple network with security group enabled? select one of them..."); + } + return networks.get(0); + } @Override public PublicIpAddress getPublicIpAddress(long ipAddressId) { @@ -2205,7 +2219,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag // create new Virtual network for the user if it doesn't exist if (createNetwork) { List offerings = _configMgr.listNetworkOfferings(TrafficType.Guest, false); - network = createNetwork(offerings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", false, true, zoneId, null, null, null, null, owner); + network = createNetwork(offerings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", false, true, zoneId, null, null, null, null, owner, false); if (network == null) { s_logger.warn("Failed to create default Virtual network for the account " + accountId + "in zone " + zoneId); diff --git a/server/src/com/cloud/network/NetworkVO.java b/server/src/com/cloud/network/NetworkVO.java index 2352b75d4d1..32c7fdf1d32 100644 --- a/server/src/com/cloud/network/NetworkVO.java +++ b/server/src/com/cloud/network/NetworkVO.java @@ -134,6 +134,9 @@ public class NetworkVO implements Network { @Column(name="is_default") boolean isDefault; + @Column(name="is_security_group_enabled") + boolean securityGroupEnabled = false; + public NetworkVO() { } @@ -161,7 +164,7 @@ public class NetworkVO implements Network { this.guestType = guestType; } - public NetworkVO(long id, Network that, long offeringId, long dataCenterId, String guruName, long domainId, long accountId, long related, String name, String displayText, Boolean isShared, boolean isDefault) { + public NetworkVO(long id, Network that, long offeringId, long dataCenterId, String guruName, long domainId, long accountId, long related, String name, String displayText, Boolean isShared, boolean isDefault, boolean isSecurityGroupEnabled) { this(id, that.getTrafficType(), that.getGuestType(), that.getMode(), that.getBroadcastDomainType(), offeringId, dataCenterId, domainId, accountId, related, name, displayText, isShared, isDefault); this.gateway = that.getGateway(); this.cidr = that.getCidr(); @@ -170,6 +173,7 @@ public class NetworkVO implements Network { this.guruName = guruName; this.state = that.getState(); this.networkDomain = that.getNetworkDomain(); + this.securityGroupEnabled = isSecurityGroupEnabled; if (state == null) { state = State.Allocated; } @@ -381,6 +385,15 @@ public class NetworkVO implements Network { public boolean isDefault() { return isDefault; } + + @Override + public boolean isSecurityGroupEnabled() { + return securityGroupEnabled; + } + + public void setSecurityGroupEnabled(boolean enabled) { + this.securityGroupEnabled = enabled; + } public void setShared(boolean isShared) { this.isShared = isShared; diff --git a/server/src/com/cloud/network/dao/NetworkDao.java b/server/src/com/cloud/network/dao/NetworkDao.java index 31cbfed9385..b775f62c33e 100644 --- a/server/src/com/cloud/network/dao/NetworkDao.java +++ b/server/src/com/cloud/network/dao/NetworkDao.java @@ -58,4 +58,5 @@ public interface NetworkDao extends GenericDao { int getActiveNicsIn(long networkId); List findNetworksToGarbageCollect(); void clearCheckForGc(long networkId); + List listByZoneSecurityGroup(Long zoneId); } diff --git a/server/src/com/cloud/network/dao/NetworkDaoImpl.java b/server/src/com/cloud/network/dao/NetworkDaoImpl.java index 05e84ce8601..376113bb145 100644 --- a/server/src/com/cloud/network/dao/NetworkDaoImpl.java +++ b/server/src/com/cloud/network/dao/NetworkDaoImpl.java @@ -49,6 +49,7 @@ public class NetworkDaoImpl extends GenericDaoBase implements N final SearchBuilder RelatedConfigSearch; final SearchBuilder AccountNetworkSearch; final SearchBuilder ZoneBroadcastUriSearch; + final SearchBuilder ZoneSecurityGroupSearch; NetworkAccountDaoImpl _accountsDao = ComponentLocator.inject(NetworkAccountDaoImpl.class); NetworkOpDaoImpl _opDao = ComponentLocator.inject(NetworkOpDaoImpl.class); @@ -100,6 +101,11 @@ public class NetworkDaoImpl extends GenericDaoBase implements N ZoneBroadcastUriSearch.and("broadcastUri", ZoneBroadcastUriSearch.entity().getBroadcastUri(), Op.EQ); ZoneBroadcastUriSearch.done(); + ZoneSecurityGroupSearch = createSearchBuilder(); + ZoneSecurityGroupSearch.and("dataCenterId", ZoneSecurityGroupSearch.entity().getDataCenterId(), Op.EQ); + ZoneSecurityGroupSearch.and("securityGroup", ZoneSecurityGroupSearch.entity().isSecurityGroupEnabled(), Op.EQ); + ZoneSecurityGroupSearch.done(); + _tgMacAddress = _tgs.get("macAddress"); } @@ -230,6 +236,15 @@ public class NetworkDaoImpl extends GenericDaoBase implements N return search(sc, null); } + @Override + public List listByZoneSecurityGroup(Long zoneId) { + SearchCriteria sc = ZoneSecurityGroupSearch.create(); + if (zoneId != null) + sc.setParameters("dataCenterId", zoneId); + sc.setParameters("securityGroup", true); + return search(sc, null); + } + @Override public void changeActiveNicsBy(long networkId, int count) { _opDao.changeActiveNicsBy(networkId, count); diff --git a/server/src/com/cloud/network/guru/PublicNetworkGuru.java b/server/src/com/cloud/network/guru/PublicNetworkGuru.java index c90e097080b..a1e6123996f 100644 --- a/server/src/com/cloud/network/guru/PublicNetworkGuru.java +++ b/server/src/com/cloud/network/guru/PublicNetworkGuru.java @@ -19,6 +19,7 @@ import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientVirtualNetworkCapcityException; import com.cloud.network.IPAddressVO; import com.cloud.network.Network; +import com.cloud.network.Network.GuestIpType; import com.cloud.network.Network.State; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkProfile; @@ -70,7 +71,12 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { } if (offering.getTrafficType() == TrafficType.Public) { - NetworkVO ntwk = new NetworkVO(offering.getTrafficType(), null, Mode.Static, BroadcastDomainType.Vlan, offering.getId(), plan.getDataCenterId(), State.Setup); + GuestIpType type = null; + if (network.isSecurityGroupEnabled()) { + type = GuestIpType.Direct; + } + + NetworkVO ntwk = new NetworkVO(offering.getTrafficType(), type, Mode.Static, BroadcastDomainType.Vlan, offering.getId(), plan.getDataCenterId(), State.Setup); return ntwk; } else { return null; @@ -83,7 +89,14 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { protected void getIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { if (nic.getIp4Address() == null) { - PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), null, vm.getOwner(), VlanType.VirtualNetwork, null); + VlanType type = VlanType.VirtualNetwork; + Long networkId = null; + if (network.isSecurityGroupEnabled()) { + type = VlanType.DirectAttached; + networkId = network.getId(); + } + + PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), null, vm.getOwner(), type, networkId); nic.setIp4Address(ip.getAddress().toString()); nic.setGateway(ip.getGateway()); nic.setNetmask(ip.getNetmask()); diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 46a63bdaf2a..d85f27f853e 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -849,7 +849,9 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian if (dc.getNetworkType() == NetworkType.Advanced) { String cidr = network.getCidr(); - dhcpRange = NetUtils.getDhcpRange(cidr); + if (cidr != null) { + dhcpRange = NetUtils.getDhcpRange(cidr); + } } if (router.getRole() == Role.DHCP_USERDATA) { diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java index ba81dd1c5dd..6e41477ed00 100644 --- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java +++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java @@ -84,6 +84,7 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.StateListener; import com.cloud.utils.net.NetUtils; +import com.cloud.vm.UserVmManager; import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; @@ -108,6 +109,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG @Inject DomainDao _domainDao; @Inject AgentManager _agentMgr; @Inject VirtualMachineManager _itMgr; + @Inject UserVmManager _userVmMgr; ScheduledExecutorService _executorPool; ScheduledExecutorService _cleanupExecutor; @@ -115,8 +117,6 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG private final long _timeBetweenCleanups = 30; //seconds - - boolean _enabled = false; SecurityGroupListener _answerListener; @@ -300,7 +300,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG } protected void handleVmStarted(VMInstanceVO vm) { - if (vm.getType() != VirtualMachine.Type.User || !_enabled) + if (vm.getType() != VirtualMachine.Type.User || !isVmSecurityGroupEnabled(vm.getId())) return; Set affectedVms = getAffectedVmsForVmStart(vm); scheduleRulesetUpdateToHosts(affectedVms, true, null); @@ -308,9 +308,6 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG @DB public void scheduleRulesetUpdateToHosts(Set affectedVms, boolean updateSeqno, Long delayMs) { - if (!_enabled) { - return; - } if (delayMs == null) { delayMs = new Long(100l); } @@ -413,7 +410,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG } protected void handleVmStopped(VMInstanceVO vm) { - if (vm.getType() != VirtualMachine.Type.User || !_enabled) + if (vm.getType() != VirtualMachine.Type.User || !isVmSecurityGroupEnabled(vm.getId())) return; Set affectedVms = getAffectedVmsForVmStop(vm); scheduleRulesetUpdateToHosts(affectedVms, true, null); @@ -450,10 +447,6 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG Integer endPortOrCode = null; Long accountId = null; - if (!_enabled) { - return null; - } - //Verify input parameters if (protocol == null) { protocol = "all"; @@ -653,11 +646,6 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG @Override @DB public boolean revokeSecurityGroupIngress(RevokeSecurityGroupIngressCmd cmd) { - - if (!_enabled) { - return false; - } - //input validation Account account = UserContext.current().getCaller(); Long domainId = cmd.getDomainId(); @@ -741,9 +729,6 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG @Override public SecurityGroupVO createSecurityGroup(CreateSecurityGroupCmd cmd) throws PermissionDeniedException, InvalidParameterValueException { - if (!_enabled) { - return null; - } String accountName = cmd.getAccountName(); Long domainId = cmd.getDomainId(); @@ -802,9 +787,6 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG @DB @Override public SecurityGroupVO createSecurityGroup(String name, String description, Long domainId, Long accountId, String accountName) { - if (!_enabled) { - return null; - } final Transaction txn = Transaction.currentTxn(); AccountVO account = null; txn.start(); @@ -835,13 +817,6 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG /*register state listener, no matter security group is enabled or not*/ VirtualMachine.State.getStateMachine().registerListener(this); - String enabled =_configDao.getValue("direct.attach.security.groups.enabled"); - if ("true".equalsIgnoreCase(enabled)) { - _enabled = true; - } - if (!_enabled) { - return false; - } _answerListener = new SecurityGroupListener(this, _agentMgr, _workDao); _agentMgr.registerForHostEvents(_answerListener, true, true, true); @@ -861,9 +836,6 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG @Override public boolean start() { - if (!_enabled) { - return true; - } _cleanupExecutor.scheduleAtFixedRate(new CleanupThread(), _timeBetweenCleanups, _timeBetweenCleanups, TimeUnit.SECONDS); return true; } @@ -876,9 +848,6 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG @Override public SecurityGroupVO createDefaultSecurityGroup(Long accountId) { - if (!_enabled) { - return null; - } SecurityGroupVO groupVO = _securityGroupDao.findByAccountAndName(accountId, SecurityGroupManager.DEFAULT_GROUP_NAME); if (groupVO == null ) { Account accVO = _accountDao.findById(accountId); @@ -947,7 +916,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG @Override @DB public boolean addInstanceToGroups(final Long userVmId, final List groups) { - if (!_enabled) { + if (!isVmSecurityGroupEnabled(userVmId)) { return true; } if (groups != null && !groups.isEmpty()) { @@ -995,7 +964,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG @Override @DB public void removeInstanceFromGroups(Long userVmId) { - if (!_enabled) { + if (!isVmSecurityGroupEnabled(userVmId)) { return; } final Transaction txn = Transaction.currentTxn(); @@ -1018,10 +987,6 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG Long domainId = cmd.getDomainId(); Account account = UserContext.current().getCaller(); - if (!_enabled) { - return true; - } - //Verify input parameters Long accountId = null; if ((account == null) || isAdmin(account.getType())) { @@ -1343,4 +1308,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG return true; } + private boolean isVmSecurityGroupEnabled(Long vmId) { + return _userVmMgr.isVmSecurityGroupEnabled(vmId); + } } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 920659295d2..a8e5555c9f4 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -183,6 +183,8 @@ import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.info.ConsoleProxyInfo; import com.cloud.network.IPAddressVO; +import com.cloud.network.Network; +import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; @@ -320,6 +322,7 @@ public class ManagementServerImpl implements ManagementServer { private final NetworkDao _networkDao; private final StorageManager _storageMgr; private final VirtualMachineManager _itMgr; + private final NetworkManager _networkMgr; private final Adapters _userAuthenticators; private final HostPodDao _hostPodDao; @@ -407,6 +410,7 @@ public class ManagementServerImpl implements ManagementServer { _uploadMonitor = locator.getManager(UploadMonitor.class); _sshKeyPairDao = locator.getDao(SSHKeyPairDao.class); _itMgr = locator.getManager(VirtualMachineManager.class); + _networkMgr = locator.getManager(NetworkManager.class); _userAuthenticators = locator.getAdapters(UserAuthenticator.class); if (_userAuthenticators == null || !_userAuthenticators.isSet()) { @@ -4185,8 +4189,12 @@ public class ManagementServerImpl implements ManagementServer { @Override public Map listCapabilities(ListCapabilitiesCmd cmd) { Map capabilities = new HashMap(); + String securityGroupsEnabled = "false"; + Network net = _networkMgr.getNetworkWithSecurityGroupEnabled(null); + if (net != null) { + securityGroupsEnabled = "true"; + } - String securityGroupsEnabled = _configs.get(Config.DirectAttachSecurityGroupsEnabled.key()); String userPublicTemplateEnabled = _configs.get(Config.AllowPublicUserTemplates.key()); capabilities.put("securityGroupsEnabled", (securityGroupsEnabled == null || securityGroupsEnabled.equals("false") ? false : true)); diff --git a/server/src/com/cloud/vm/UserVmManager.java b/server/src/com/cloud/vm/UserVmManager.java index e9a3e4d4e04..f4304f3c788 100644 --- a/server/src/com/cloud/vm/UserVmManager.java +++ b/server/src/com/cloud/vm/UserVmManager.java @@ -88,4 +88,8 @@ public interface UserVmManager extends VirtualMachineGuru{ */ List searchForUserVMs(Criteria c); + boolean isVmSecurityGroupEnabled(Long vmId); + + + } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 53f32128a82..d8a991a47ef 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2009,8 +2009,35 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } } + List sgs = cmd.getSecurityGroupIdList(); + if (sgs != null && !sgs.isEmpty()) { + if (networkList == null || networkList.isEmpty()) { + Network networkWithSecurityGroup = _networkMgr.getNetworkWithSecurityGroupEnabled(dc.getId()); + if (networkWithSecurityGroup == null) { + throw new InvalidParameterValueException("No network with security enabled"); + } + networkList = new ArrayList(); + networkList.add(networkWithSecurityGroup.getId()); + } else { + if (networkList.size() > 1) { + throw new InvalidParameterValueException("Only support one network per VM if security group enabled"); + } + + Network net = _networkMgr.getNetwork(networkList.get(0).longValue()); + if (!net.isSecurityGroupEnabled()) { + throw new InvalidParameterValueException("need to enable security group for network: " + net.getId()); + } + } + } + if (networkList == null || networkList.isEmpty()) { - throw new InvalidParameterValueException("NetworkIds have to be specified"); + Network networkWithSecurityGroup = _networkMgr.getNetworkWithSecurityGroupEnabled(dc.getId()); + if (networkWithSecurityGroup != null) { + networkList = new ArrayList(); + networkList.add(networkWithSecurityGroup.getId()); + } else { + throw new InvalidParameterValueException("NetworkIds have to be specified"); + } } List> networks = new ArrayList>(); @@ -2676,4 +2703,16 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager return _vmDao.search(sc, searchFilter); } + + @Override + public boolean isVmSecurityGroupEnabled(Long vmId) { + List nics = _nicDao.listByVmId(vmId); + for (NicVO nic : nics) { + Network network = _networkDao.findById(nic.getNetworkId()); + if (network != null && network.isSecurityGroupEnabled()) { + return true; + } + } + return false; + } } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 05fb06e8502..625e1f1b85f 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -179,6 +179,7 @@ CREATE TABLE `cloud`.`networks` ( `is_default` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if network is default', `created` datetime NOT NULL COMMENT 'date created', `removed` datetime COMMENT 'date removed if not null', + `is_security_group_enabled` smallint(1) NOT NULL COMMENT '1: enabled, 0: not', PRIMARY KEY (`id`), CONSTRAINT `fk_networks__network_offering_id` FOREIGN KEY (`network_offering_id`) REFERENCES `network_offerings`(`id`), CONSTRAINT `fk_networks__data_center_id` FOREIGN KEY (`data_center_id`) REFERENCES `data_center`(`id`), diff --git a/setup/db/templates.sql b/setup/db/templates.sql index 6d074c3825b..9f98f070183 100755 --- a/setup/db/templates.sql +++ b/setup/db/templates.sql @@ -7,7 +7,7 @@ INSERT INTO `cloud`.`vm_template` (id, unique_name, name, public, created, type, VALUES (3, 'routing-3', 'SystemVM Template (KVM)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/releases/2.2.0/systemvm.qcow2.bz2', 'ec463e677054f280f152fcc264255d2f', 0, 'SystemVM Template (KVM)', 'QCOW2', 15, 0, 1, 'KVM'); INSERT INTO `cloud`.`vm_template` (id, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, display_text, enable_password, format, guest_os_id, featured, cross_zones, hypervisor_type, extractable) - VALUES (4, 'centos55-x86_64', 'CentOS 5.5(64-bit) no GUI (KVM)', 1, now(), 'BUILTIN', 0, 64, 1, 'http://download.cloud.com/templates/builtin/eec2209b-9875-3c8d-92be-c001bd8a0faf.qcow2.bz2', 'ed0e788280ff2912ea40f7f91ca7a249', 'CentOS 5.5(64-bit) no GUI (KVM)', 0, 'QCOW2', 112, 1, 1, 'KVM', 1); + VALUES (4, 'centos55-x86_64', 'CentOS 5.5(64-bit) no GUI (KVM)', 1, now(), 'BUILTIN', 0, 64, 1, 'http://download.cloud.com/releases/2.2.0/eec2209b-9875-3c8d-92be-c001bd8a0faf.qcow2.bz2', 'ed0e788280ff2912ea40f7f91ca7a249', 'CentOS 5.5(64-bit) no GUI (KVM)', 0, 'QCOW2', 112, 1, 1, 'KVM', 1); INSERT INTO `cloud`.`vm_template` (id, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones, hypervisor_type, extractable) VALUES (7, 'centos53-x64', 'CentOS 5.3(64-bit) no GUI (vSphere)', 1, now(), 'BUILTIN', 0, 64, 1, 'http://download.cloud.com/releases/2.2.0/CentOS5.3-x86_64.ova', 'f6f881b7f2292948d8494db837fe0f47', 0, 'CentOS 5.3(64-bit) no GUI (vSphere)', 'OVA', 12, 1, 1, 'VMware', 1);