From 9c9e2ec9ccd2609246610c798d4a8d8f3bc5aee7 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Wed, 1 May 2013 13:23:08 -0700 Subject: [PATCH 01/36] PVLAN: Add pvlan in createNetworkCommand --- api/src/com/cloud/network/Networks.java | 1 + .../apache/cloudstack/api/ApiConstants.java | 1 + .../user/network/CreateNetworkCmd.java | 7 ++++ .../xen/resource/CitrixResourceBase.java | 5 +++ .../ConfigurationManagerImpl.java | 2 ++ .../src/com/cloud/network/NetworkManager.java | 3 +- .../com/cloud/network/NetworkManagerImpl.java | 35 +++++++++++++------ .../com/cloud/network/NetworkServiceImpl.java | 13 +++++-- .../com/cloud/network/vpc/VpcManagerImpl.java | 2 +- .../src/com/cloud/vm/UserVmManagerImpl.java | 4 +-- .../cloud/network/MockNetworkManagerImpl.java | 2 +- .../com/cloud/vpc/MockNetworkManagerImpl.java | 3 +- utils/src/com/cloud/utils/net/NetUtils.java | 26 ++++++++++++++ .../com/cloud/utils/net/NetUtilsTest.java | 8 +++++ 14 files changed, 93 insertions(+), 19 deletions(-) diff --git a/api/src/com/cloud/network/Networks.java b/api/src/com/cloud/network/Networks.java index f085e9f3029..5aede053d50 100755 --- a/api/src/com/cloud/network/Networks.java +++ b/api/src/com/cloud/network/Networks.java @@ -63,6 +63,7 @@ public class Networks { Storage("storage", Integer.class), Lswitch("lswitch", String.class), Mido("mido", String.class), + Pvlan("pvlan", String.class), UnDecided(null, null); private String scheme; diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 1165c7b34f6..9581f54ca61 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -223,6 +223,7 @@ public class ApiConstants { public static final String VLAN = "vlan"; public static final String REMOVE_VLAN="removevlan"; public static final String VLAN_ID = "vlanid"; + public static final String ISOLATED_PVLAN = "isolatedpvlan"; public static final String VM_AVAILABLE = "vmavailable"; public static final String VM_LIMIT = "vmlimit"; public static final String VM_TOTAL = "vmtotal"; diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java index fc7bd9fdd3f..7f699fe0cc9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java @@ -86,6 +86,9 @@ public class CreateNetworkCmd extends BaseCmd { @Parameter(name=ApiConstants.VLAN, type=CommandType.STRING, description="the ID or VID of the network") private String vlan; + @Parameter(name=ApiConstants.ISOLATED_PVLAN, type=CommandType.STRING, description="the isolated private vlan for this network") + private String isolatedPvlan; + @Parameter(name=ApiConstants.NETWORK_DOMAIN, type=CommandType.STRING, description="network domain") private String networkDomain; @@ -141,6 +144,10 @@ public class CreateNetworkCmd extends BaseCmd { return vlan; } + public String getIsolatedPvlan() { + return isolatedPvlan; + } + public String getAccountName() { return accountName; } diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 46ae35a4a54..176dc00ec0e 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -1014,6 +1014,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } else if (nic.getBroadcastType() == BroadcastDomainType.Lswitch) { // Nicira Logical Switch return network.getNetwork(); + } else if (nic.getBroadcastType() == BroadcastDomainType.Pvlan) { + URI broadcastUri = nic.getBroadcastUri(); + assert broadcastUri.getScheme().equals(BroadcastDomainType.Pvlan.scheme()); + long vlan = Long.parseLong(NetUtils.getPrimaryPvlanFromUri(broadcastUri)); + return enableVlanNetwork(conn, vlan, network); } throw new CloudRuntimeException("Unable to support this type of network broadcast domain: " + nic.getBroadcastUri()); diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 37ca793c556..a47f3b3c80f 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -2505,6 +2505,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (uri != null) { String[] vlan = uri.toString().split("vlan:\\/\\/"); networkVlanId = vlan[1]; + //For pvlan + networkVlanId = networkVlanId.split("-")[0]; } if (vlanId != null) { diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index 4af716ca12a..e11135161db 100755 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -128,7 +128,8 @@ public interface NetworkManager { Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, Long domainId, PhysicalNetwork physicalNetwork, - long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String ip6Gateway, String ip6Cidr) + long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String ip6Gateway, String ip6Cidr, + String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException; /** diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 5179e872686..7a09eb553f8 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -1874,7 +1874,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L @DB public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, Long domainId, - PhysicalNetwork pNtwk, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String ip6Gateway, String ip6Cidr) + PhysicalNetwork pNtwk, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, + String ip6Gateway, String ip6Cidr, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId); @@ -1964,6 +1965,9 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L if (ipv6) { throw new InvalidParameterValueException("IPv6 is not supported with security group!"); } + if (isolatedPvlan != null) { + throw new InvalidParameterValueException("Isolated Private VLAN is not supported with security group!"); + } // Only Account specific Isolated network with sourceNat service disabled are allowed in security group // enabled zone if ( ntwkOff.getGuestType() != GuestType.Shared ){ @@ -2094,13 +2098,20 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } if (vlanId != null) { - userNetwork.setBroadcastUri(URI.create("vlan://" + vlanId)); - userNetwork.setBroadcastDomainType(BroadcastDomainType.Vlan); - if (!vlanId.equalsIgnoreCase(Vlan.UNTAGGED)) { - userNetwork.setBroadcastDomainType(BroadcastDomainType.Vlan); - } else { - userNetwork.setBroadcastDomainType(BroadcastDomainType.Native); - } + if (isolatedPvlan == null) { + userNetwork.setBroadcastUri(URI.create("vlan://" + vlanId)); + if (!vlanId.equalsIgnoreCase(Vlan.UNTAGGED)) { + userNetwork.setBroadcastDomainType(BroadcastDomainType.Vlan); + } else { + userNetwork.setBroadcastDomainType(BroadcastDomainType.Native); + } + } else { + if (vlanId.equalsIgnoreCase(Vlan.UNTAGGED)) { + throw new InvalidParameterValueException("Cannot support pvlan with untagged primary vlan!"); + } + userNetwork.setBroadcastUri(NetUtils.generateUriForPvlan(vlanId, isolatedPvlan)); + userNetwork.setBroadcastDomainType(BroadcastDomainType.Pvlan); + } } List networks = setupNetwork(owner, ntwkOff, userNetwork, plan, name, displayText, true, domainId, @@ -2697,7 +2708,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L guestNetwork = createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network" , owner.getAccountName() + "-network", null, null, null, null, owner, null, physicalNetwork, zoneId, ACLType.Account, - null, null, null, null); + null, null, null, null, null); if (guestNetwork == null) { s_logger.warn("Failed to create default Virtual network for the account " + accountId + "in zone " + zoneId); throw new CloudRuntimeException("Failed to create a Guest Isolated Networks with SourceNAT " + @@ -3551,8 +3562,10 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L nic.setGateway(ip.getGateway()); nic.setNetmask(ip.getNetmask()); nic.setIsolationUri(IsolationType.Vlan.toUri(ip.getVlanTag())); - nic.setBroadcastType(BroadcastDomainType.Vlan); - nic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(ip.getVlanTag())); + //nic.setBroadcastType(BroadcastDomainType.Vlan); + //nic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(ip.getVlanTag())); + nic.setBroadcastType(network.getBroadcastDomainType()); + nic.setBroadcastUri(network.getBroadcastUri()); nic.setFormat(AddressFormat.Ip4); nic.setReservationId(String.valueOf(ip.getVlanTag())); nic.setMacAddress(ip.getMacAddress()); diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 2dcb47d0cd8..7c4d7027c6b 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -828,6 +828,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { String endIPv6 = cmd.getEndIpv6(); String ip6Gateway = cmd.getIp6Gateway(); String ip6Cidr = cmd.getIp6Cidr(); + String isolatedPvlan = cmd.getIsolatedPvlan(); // Validate network offering NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId); @@ -1014,6 +1015,10 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } } + if (isolatedPvlan != null && (zone.getNetworkType() != NetworkType.Advanced || ntwkOff.getGuestType() != Network.GuestType.Shared)) { + throw new InvalidParameterValueException("Can only support create Private VLAN network with advance shared network!"); + } + // Regular user can create Guest Isolated Source Nat enabled network only if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL && (ntwkOff.getTrafficType() != TrafficType.Guest || ntwkOff.getGuestType() != Network.GuestType.Isolated @@ -1045,6 +1050,9 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (ipv6 && providersConfiguredForExternalNetworking(ntwkProviders)) { throw new InvalidParameterValueException("Cannot support IPv6 on network offering with external devices!"); } + if (isolatedPvlan != null && providersConfiguredForExternalNetworking(ntwkProviders)) { + throw new InvalidParameterValueException("Cannot support private vlan on network offering with external devices!"); + } if (cidr != null && providersConfiguredForExternalNetworking(ntwkProviders)) { if (ntwkOff.getGuestType() == GuestType.Shared && (zone.getNetworkType() == NetworkType.Advanced) && @@ -1115,7 +1123,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { throw new InvalidParameterValueException("Network offering can be used for VPC networks only"); } network = _networkMgr.createGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId, - networkDomain, owner, sharedDomainId, pNtwk, zoneId, aclType, subdomainAccess, vpcId, ip6Gateway, ip6Cidr); + networkDomain, owner, sharedDomainId, pNtwk, zoneId, aclType, subdomainAccess, vpcId, + ip6Gateway, ip6Cidr, isolatedPvlan); } if (caller.getType() == Account.ACCOUNT_TYPE_ADMIN && createVlan) { @@ -3363,7 +3372,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (privateNetwork == null) { //create Guest network privateNetwork = _networkMgr.createGuestNetwork(ntwkOff.getId(), networkName, displayText, gateway, cidr, vlan, - null, owner, null, pNtwk, pNtwk.getDataCenterId(), ACLType.Account, null, null, null, null); + null, owner, null, pNtwk, pNtwk.getDataCenterId(), ACLType.Account, null, null, null, null, null); s_logger.debug("Created private network " + privateNetwork); } else { s_logger.debug("Private network already exists: " + privateNetwork); diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index bc7bb0c75f2..18690d72ed5 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -1965,7 +1965,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis //2) Create network Network guestNetwork = _ntwkMgr.createGuestNetwork(ntwkOffId, name, displayText, gateway, cidr, vlanId, - networkDomain, owner, domainId, pNtwk, zoneId, aclType, subdomainAccess, vpcId, null, null); + networkDomain, owner, domainId, pNtwk, zoneId, aclType, subdomainAccess, vpcId, null, null, null); return guestNetwork; } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 617994888bd..8f2d103d343 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2164,7 +2164,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use s_logger.debug("Creating network for account " + owner + " from the network offering id=" +requiredOfferings.get(0).getId() + " as a part of deployVM process"); Network newNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", null, null, - null, null, owner, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null); + null, null, owner, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null, null); defaultNetwork = _networkDao.findById(newNetwork.getId()); } else if (virtualNetworks.size() > 1) { throw new InvalidParameterValueException( @@ -4005,7 +4005,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use requiredOfferings.get(0).getId() + " as a part of deployVM process"); Network newNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), newAccount.getAccountName() + "-network", newAccount.getAccountName() + "-network", null, null, - null, null, newAccount, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null); + null, null, newAccount, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null, null); // if the network offering has persistent set to true, implement the network if (requiredOfferings.get(0).getIsPersistent()) { DeployDestination dest = new DeployDestination(zone, null, null, null); diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java index e9987bd1b66..3381d60c564 100755 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -249,7 +249,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage @Override public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, Long domainId, - PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String gatewayv6, String cidrv6) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { + PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String gatewayv6, String cidrv6, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { // TODO Auto-generated method stub return null; } diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index 9b18358e258..7dcc970405b 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -831,7 +831,8 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage @Override public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, Long domainId, - PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String gatewayv6, String cidrv6) + PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, + String gatewayv6, String cidrv6, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { // TODO Auto-generated method stub return null; diff --git a/utils/src/com/cloud/utils/net/NetUtils.java b/utils/src/com/cloud/utils/net/NetUtils.java index 5988dd5f337..4dd404d4cc3 100755 --- a/utils/src/com/cloud/utils/net/NetUtils.java +++ b/utils/src/com/cloud/utils/net/NetUtils.java @@ -24,6 +24,7 @@ import java.net.InetAddress; import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.net.SocketException; +import java.net.URI; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Formatter; @@ -1290,4 +1291,29 @@ public class NetUtils { } return resultIp; } + + public static URI generateUriForPvlan(String primaryVlan, String isolatedPvlan) { + return URI.create("pvlan://" + primaryVlan + "-i" + isolatedPvlan); + } + + public static String getPrimaryPvlanFromUri(URI uri) { + String[] vlans = uri.getHost().split("-"); + if (vlans.length < 1) { + return null; + } + return vlans[0]; + } + + public static String getIsolatedPvlanFromUri(URI uri) { + String[] vlans = uri.getHost().split("-"); + if (vlans.length < 2) { + return null; + } + for (String vlan : vlans) { + if (vlan.startsWith("i")) { + return vlan.replace("i", " ").trim(); + } + } + return null; + } } diff --git a/utils/test/com/cloud/utils/net/NetUtilsTest.java b/utils/test/com/cloud/utils/net/NetUtilsTest.java index 28bd71f18d7..16d3402f0e6 100644 --- a/utils/test/com/cloud/utils/net/NetUtilsTest.java +++ b/utils/test/com/cloud/utils/net/NetUtilsTest.java @@ -17,6 +17,7 @@ package com.cloud.utils.net; import java.math.BigInteger; +import java.net.URI; import java.util.SortedSet; import java.util.TreeSet; @@ -128,4 +129,11 @@ public class NetUtilsTest extends TestCase { assertFalse(NetUtils.isIp6InRange("1234:5678:abcd::1", null)); assertTrue(NetUtils.isIp6InRange("1234:5678:abcd::1", "1234:5678::1-1234:5679::1")); } + + public void testPvlan() { + URI uri = NetUtils.generateUriForPvlan("123", "456"); + assertTrue(uri.toString().equals("pvlan://123-i456")); + assertTrue(NetUtils.getPrimaryPvlanFromUri(uri).equals("123")); + assertTrue(NetUtils.getIsolatedPvlanFromUri(uri).equals("456")); + } } From b64039bafd194be78f0a873d4b2431d01931febf Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Wed, 1 May 2013 13:23:08 -0700 Subject: [PATCH 02/36] Implement PVLAN on Xen Start/stop vm/dhcp server are done. Not done with VM migration. A new command(PvlanSetupCommand) is sent for setting up PVLAN for vms. Currently it's focus on OVS implementation. Need to be more abstruct and add vSwitch part. --- .../cloud/agent/api/PvlanSetupCommand.java | 130 ++++++++++++++ .../xen/resource/CitrixResourceBase.java | 46 ++++- scripts/vm/hypervisor/xenserver/ovs-pvlan | 168 ++++++++++++++++++ .../vm/hypervisor/xenserver/xenserver60/patch | 6 +- scripts/vm/network/ovs-pvlan-cleanup.sh | 23 +++ scripts/vm/network/ovs-pvlan-dhcp-host.sh | 104 +++++++++++ .../vm/network/ovs-pvlan-vm-in-dhcp-host.sh | 88 +++++++++ scripts/vm/network/ovs-pvlan-vm.sh | 90 ++++++++++ .../network/element/VirtualRouterElement.java | 11 ++ .../VirtualNetworkApplianceManager.java | 4 + .../VirtualNetworkApplianceManagerImpl.java | 87 ++++++++- .../src/com/cloud/vm/UserVmManagerImpl.java | 45 +++++ ...MockVpcVirtualNetworkApplianceManager.java | 7 + 13 files changed, 804 insertions(+), 5 deletions(-) create mode 100644 api/src/com/cloud/agent/api/PvlanSetupCommand.java create mode 100755 scripts/vm/hypervisor/xenserver/ovs-pvlan create mode 100755 scripts/vm/network/ovs-pvlan-cleanup.sh create mode 100755 scripts/vm/network/ovs-pvlan-dhcp-host.sh create mode 100755 scripts/vm/network/ovs-pvlan-vm-in-dhcp-host.sh create mode 100755 scripts/vm/network/ovs-pvlan-vm.sh diff --git a/api/src/com/cloud/agent/api/PvlanSetupCommand.java b/api/src/com/cloud/agent/api/PvlanSetupCommand.java new file mode 100644 index 00000000000..22a828afa8b --- /dev/null +++ b/api/src/com/cloud/agent/api/PvlanSetupCommand.java @@ -0,0 +1,130 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api; + +import java.net.URI; + +import com.cloud.utils.net.NetUtils; + +public class PvlanSetupCommand extends Command { + public enum Type { + DHCP, + VM, + VM_IN_DHCP_HOST + } + private String op; + private String bridge; + private String primary; + private String isolated; + private String vmMac; + private String dhcpMac; + private String dhcpIp; + private boolean strict; + private Type type; + + protected PvlanSetupCommand() {} + + protected PvlanSetupCommand(Type type, String op, String bridge, URI uri) + { + this.type = type; + this.op = op; + this.bridge = bridge; + this.primary = NetUtils.getPrimaryPvlanFromUri(uri); + this.isolated = NetUtils.getIsolatedPvlanFromUri(uri); + this.strict = true; + } + + static public PvlanSetupCommand createDhcpSetup(String op, String bridge, URI uri, String dhcpMac, String dhcpIp) + { + PvlanSetupCommand cmd = new PvlanSetupCommand(Type.DHCP, op, bridge, uri); + cmd.setDhcpMac(dhcpMac); + cmd.setDhcpIp(dhcpIp); + return cmd; + } + + static public PvlanSetupCommand createVmSetup(String op, String bridge, URI uri, String vmMac) + { + PvlanSetupCommand cmd = new PvlanSetupCommand(Type.VM, op, bridge, uri); + cmd.setVmMac(vmMac); + return cmd; + } + + static public PvlanSetupCommand createVmInDhcpHostSetup(String op, String bridge, URI uri, String dhcpMac, String vmMac) + { + PvlanSetupCommand cmd = new PvlanSetupCommand(Type.VM_IN_DHCP_HOST, op, bridge, uri); + cmd.setDhcpMac(dhcpMac); + cmd.setVmMac(vmMac); + return cmd; + } + + @Override + public boolean executeInSequence() { + return true; + } + + public String getOp() { + return op; + } + + public String getBridge() { + return bridge; + } + + public String getPrimary() { + return primary; + } + + public String getIsolated() { + return isolated; + } + + public String getVmMac() { + return vmMac; + } + + protected void setVmMac(String vmMac) { + this.vmMac = vmMac; + } + + public String getDhcpMac() { + return dhcpMac; + } + + protected void setDhcpMac(String dhcpMac) { + this.dhcpMac = dhcpMac; + } + + public String getDhcpIp() { + return dhcpIp; + } + + protected void setDhcpIp(String dhcpIp) { + this.dhcpIp = dhcpIp; + } + + public Type getType() { + return type; + } + + public boolean isStrict() { + return strict; + } + + public void setStrict(boolean strict) { + this.strict = strict; + } +} diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 176dc00ec0e..34b590e40c9 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -604,6 +604,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return execute((NetworkRulesVmSecondaryIpCommand)cmd); } else if (clazz == ScaleVmCommand.class) { return execute((ScaleVmCommand) cmd); + } else if (clazz == PvlanSetupCommand.class) { + return execute((PvlanSetupCommand) cmd); } else { return Answer.createUnsupportedCommandAnswer(cmd); } @@ -1054,7 +1056,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vifr = vif.getRecord(conn); s_logger.debug("Created a vif " + vifr.uuid + " on " + nic.getDeviceId()); } - + return vif; } @@ -1465,6 +1467,48 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } } + + private Answer execute(PvlanSetupCommand cmd) { + Connection conn = getConnection(); + + String primaryPvlan = cmd.getPrimary(); + String isolatedPvlan = cmd.getIsolated(); + String op = cmd.getOp(); + String bridge = cmd.getBridge(); + String result = null; + String dhcpMac = cmd.getDhcpMac(); + String dhcpIp = cmd.getDhcpIp(); + String vmMac = cmd.getVmMac(); + if (cmd.getType() == PvlanSetupCommand.Type.DHCP) { + result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-dhcp", "op", op, "bridge", bridge, + "primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, "dhcp-ip", dhcpIp, "dhcp-mac", dhcpMac); + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to program pvlan for dhcp server with mac " + dhcpMac); + return new Answer(cmd, false, result); + } else { + s_logger.info("Programmed pvlan for dhcp server with mac " + dhcpMac); + } + } else if (cmd.getType() == PvlanSetupCommand.Type.VM) { + result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-vm-alone", "op", op, "bridge", bridge, + "primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, "vm-mac", vmMac); + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to program pvlan for vm with mac " + vmMac); + return new Answer(cmd, false, result); + } else { + s_logger.info("Programmed pvlan for vm with mac " + vmMac); + } + } else if (cmd.getType() == PvlanSetupCommand.Type.VM_IN_DHCP_HOST) { + result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-vm-dhcp", "op", op, "bridge", bridge, + "primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, "vm-mac", vmMac, "dhcp-mac", dhcpMac); + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to program pvlan for vm in dhcp host with mac " + vmMac); + return new Answer(cmd, false, result); + } else { + s_logger.info("Programmed pvlan for vm in dhcp host with mac " + vmMac); + } + } + return new Answer(cmd, true, result); + } @Override public StartAnswer execute(StartCommand cmd) { diff --git a/scripts/vm/hypervisor/xenserver/ovs-pvlan b/scripts/vm/hypervisor/xenserver/ovs-pvlan new file mode 100755 index 00000000000..2c1e3af8f77 --- /dev/null +++ b/scripts/vm/hypervisor/xenserver/ovs-pvlan @@ -0,0 +1,168 @@ +#!/usr/bin/python +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + +import cloudstack_pluginlib as lib +import logging +import os +import sys +import subprocess +import time +import XenAPIPlugin + +sys.path.append("/opt/xensource/sm/") +import util + +from time import localtime as _localtime, asctime as _asctime + +xePath = "/opt/xensource/bin/xe" +lib.setup_logging("/var/log/ovs-pvlan.log") +dhcpSetupPath = "/opt/xensource/bin/ovs-pvlan-dhcp-host.sh" +vmAloneSetupPath = "/opt/xensource/bin/ovs-pvlan-vm.sh" +vmDhcpSetupPath = "/opt/xensource/bin/ovs-pvlan-vm-in-dhcp-host.sh" +pvlanCleanupPath = "/opt/xensource/bin/ovs-pvlan-cleanup.sh" + +def echo(fn): + def wrapped(*v, **k): + name = fn.__name__ + util.SMlog("#### VMOPS enter %s ####" % name) + res = fn(*v, **k) + util.SMlog("#### VMOPS exit %s ####" % name) + return res + return wrapped + + +@echo +def setup_pvlan_dhcp(session, args): + op = args.pop("op") + bridge = args.pop("bridge") + primary = args.pop("primary-pvlan") + isolated = args.pop("isolated-pvlan") + dhcp_ip = args.pop("dhcp-ip"); + dhcp_mac = args.pop("dhcp-mac"); + + res = lib.check_switch() + if res != "SUCCESS": + return "FAILURE:%s" % res + + if op == "add": + logging.debug("About to setup dhcp vm on the switch:%s" % bridge) + res = lib.do_cmd([dhcpSetupPath, "-A", "-b", bridge, "-p", primary, + "-i", isolated, "-d", dhcp_ip, "-m", dhcp_mac]) + if res: + result = "FAILURE:%s" % res + return result; + logging.debug("Setup dhcp vm on switch program done") + elif op == "delete": + logging.debug("About to remove dhcp the switch:%s" % bridge) + res = lib.do_cmd([dhcpSetupPath, "-D", "-b", bridge, "-p", primary, + "-i", isolated, "-d", dhcp_ip, "-m", dhcp_mac]) + if res: + result = "FAILURE:%s" % res + return result; + logging.debug("Remove DHCP on switch program done") + + result = "true" + logging.debug("Setup_pvlan_dhcp completed with result:%s" % result) + return result + +@echo +def setup_pvlan_vm_alone(session, args): + op = args.pop("op") + bridge = args.pop("bridge") + isolated = args.pop("isolated-pvlan") + vm_mac = args.pop("vm-mac") + trunk_port = 1 + + res = lib.check_switch() + if res != "SUCCESS": + return "FAILURE:%s" % res + + if op == "add": + logging.debug("About to setup vm alone on the switch:%s" % bridge) + res = lib.do_cmd([vmAloneSetupPath, "-A", "-b", bridge, "-i", isolated, "-v", vm_mac]) + if res: + result = "FAILURE:%s" % res + return result; + logging.debug("Setup vm alone on switch program done") + elif op == "delete": + logging.debug("About to remove vm alone on the switch:%s" % bridge) + res = lib.do_cmd([vmAloneSetupPath, "-D", "-b", bridge, "-i", isolated, "-v", vm_mac]) + if res: + result = "FAILURE:%s" % res + return result; + logging.debug("Remove vm alone on switch program done") + + result = "true" + logging.debug("Setup_pvlan_vm_alone completed with result:%s" % result) + return result + +@echo +def setup_pvlan_vm_dhcp(session, args): + op = args.pop("op") + bridge = args.pop("bridge") + isolated = args.pop("isolated-pvlan") + vm_mac = args.pop("vm-mac") + dhcp_mac = args.pop("dhcp-mac"); + trunk_port = 1 + + res = lib.check_switch() + if res != "SUCCESS": + return "FAILURE:%s" % res + + if op == "add": + logging.debug("About to setup vm dhcp on the switch:%s" % bridge) + res = lib.do_cmd([vmDhcpSetupPath, "-A", "-b", bridge, "-i", isolated, + "-v", vm_mac, "-m", dhcp_mac]) + if res: + result = "FAILURE:%s" % res + return result; + logging.debug("Setup vm dhcp on switch program done") + elif op == "delete": + logging.debug("About to remove vm dhcp on the switch:%s" % bridge) + res = lib.do_cmd([vmDhcpSetupPath, "-D", "-b", bridge, "-i", isolated, + "-v", vm_mac, "-m", dhcp_mac]) + if res: + result = "FAILURE:%s" % res + return result; + logging.debug("Remove vm dhcp on switch program done") + + result = "true" + logging.debug("Setup_pvlan_vm_dhcp completed with result:%s" % result) + return result + +@echo +def cleanup(session, args): + res = lib.check_switch() + if res != "SUCCESS": + return "FAILURE:%s" % res + + res = lib.do_cmd([pvlanCleanUpPath]) + if res: + result = "FAILURE:%s" % res + return result; + + result = "true" + logging.debug("Setup_pvlan_vm_dhcp completed with result:%s" % result) + return result + +if __name__ == "__main__": + XenAPIPlugin.dispatch({"setup-pvlan-dhcp": setup_pvlan_dhcp, + "setup-pvlan-vm-alone": setup_pvlan_vm_alone, + "setup-pvlan-vm-dhcp": setup_pvlan_vm_dhcp, + "cleanup":cleanup}) diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch index c9125f4c5b2..c767f1af7df 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver60/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch @@ -67,4 +67,8 @@ bumpUpPriority.sh=../../../../network/domr/,0755,/opt/xensource/bin swift=..,0755,/opt/xensource/bin swiftxen=..,0755,/etc/xapi.d/plugins s3xen=..,0755,/etc/xapi.d/plugins - +ovs-pvlan=..,0755,/etc/xapi.d/plugins +ovs-pvlan-dhcp-host.sh=../../../network,0755,/opt/xensource/bin +ovs-pvlan-vm-in-dhcp-host.sh=../../../network,0755,/opt/xensource/bin +ovs-pvlan-vm.sh=../../../network,0755,/opt/xensource/bin +ovs-pvlan-cleanup.sh=../../../network,0755,/opt/xensource/bin diff --git a/scripts/vm/network/ovs-pvlan-cleanup.sh b/scripts/vm/network/ovs-pvlan-cleanup.sh new file mode 100755 index 00000000000..7493bedeff6 --- /dev/null +++ b/scripts/vm/network/ovs-pvlan-cleanup.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +#!/bin/bash + +ovs-ofctl del-flows xenbr0 +ovs-ofctl add-flow xenbr0 priority=0,actions=NORMAL + diff --git a/scripts/vm/network/ovs-pvlan-dhcp-host.sh b/scripts/vm/network/ovs-pvlan-dhcp-host.sh new file mode 100755 index 00000000000..e12fbce0f18 --- /dev/null +++ b/scripts/vm/network/ovs-pvlan-dhcp-host.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +usage() { + printf "Usage: %s: (-A|-D) -b -p -i -d -m -v -h \n" $(basename $0) >&2 + exit 2 +} + +br= +pri_vlan= +sec_iso_vlan= +dhcp_ip= +dhcp_mac= +vm_mac= +op= + +while getopts 'ADb:p:i:d:m:v:h' OPTION +do + case $OPTION in + A) op="add" + ;; + D) op="del" + ;; + b) br="$OPTARG" + ;; + p) pri_vlan="$OPTARG" + ;; + i) sec_iso_vlan="$OPTARG" + ;; + d) dhcp_ip="$OPTARG" + ;; + m) dhcp_mac="$OPTARG" + ;; + v) vm_mac="$OPTARG" + ;; + h) usage + exit 1 + ;; + esac +done + +if [ -z "$op" ] +then + echo Missing operation pararmeter! + exit 1 +fi + +if [ -z "$br" ] +then + echo Missing parameter bridge! + exit 1 +fi + +if [ -z "$pri_vlan" ] +then + echo Missing parameter primary vlan! + exit 1 +fi + +if [ -z "$sec_iso_vlan" ] +then + echo Missing parameter secondary isolate vlan! + exit 1 +fi + +if [ -z "$dhcp_ip" ] +then + echo Missing parameter DHCP IP! + exit 1 +fi + +if [ -z "$dhcp_mac" ] +then + echo Missing parameter DHCP MAC! + exit 1 +fi + +if [ "$op" == "add" ] +then + ovs-ofctl add-flow $br priority=200,arp,dl_vlan=$sec_iso_vlan,nw_dst=$dhcp_ip,actions=mod_vlan_vid:$pri_vlan,NORMAL + ovs-ofctl add-flow $br priority=180,arp,nw_dst=$dhcp_ip,actions=NORMAL + ovs-ofctl add-flow $br priority=150,dl_vlan=$sec_iso_vlan,dl_dst=$dhcp_mac,actions=mod_vlan_vid:$pri_vlan,NORMAL + ovs-ofctl add-flow $br priority=100,udp,dl_vlan=$sec_iso_vlan,nw_dst=255.255.255.255,tp_dst=67,actions=mod_vlan_vid:$pri_vlan,NORMAL +else + ovs-ofctl del-flows --strict $br priority=200,arp,dl_vlan=$sec_iso_vlan,nw_dst=$dhcp_ip + ovs-ofctl del-flows --strict $br priority=180,arp,nw_dst=$dhcp_ip + ovs-ofctl del-flows --strict $br priority=150,dl_vlan=$sec_iso_vlan,dl_dst=$dhcp_mac + ovs-ofctl del-flows --strict $br priority=100,udp,dl_vlan=$sec_iso_vlan,nw_dst=255.255.255.255,tp_dst=67 +fi diff --git a/scripts/vm/network/ovs-pvlan-vm-in-dhcp-host.sh b/scripts/vm/network/ovs-pvlan-vm-in-dhcp-host.sh new file mode 100755 index 00000000000..de37882159c --- /dev/null +++ b/scripts/vm/network/ovs-pvlan-vm-in-dhcp-host.sh @@ -0,0 +1,88 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +usage() { + printf "Usage: %s: (-A|-D) -b -p -i -d -m -v -h \n" $(basename $0) >&2 + exit 2 +} + +br= +pri_vlan= +sec_iso_vlan= +dhcp_ip= +dhcp_mac= +vm_mac= +op= + +while getopts 'ADb:p:i:d:m:v:h' OPTION +do + case $OPTION in + A) op="add" + ;; + D) op="del" + ;; + b) br="$OPTARG" + ;; + p) pri_vlan="$OPTARG" + ;; + i) sec_iso_vlan="$OPTARG" + ;; + d) dhcp_ip="$OPTARG" + ;; + m) dhcp_mac="$OPTARG" + ;; + v) vm_mac="$OPTARG" + ;; + h) usage + exit 1 + ;; + esac +done + +if [ -z "$op" ] +then + echo Missing operation pararmeter! + exit 1 +fi + +if [ -z "$br" ] +then + echo Missing parameter bridge! + exit 1 +fi + +if [ -z "$vm_mac" ] +then + echo Missing parameter VM MAC! + exit 1 +fi + +if [ -z "$dhcp_mac" ] +then + echo Missing parameter DHCP MAC! + exit 1 +fi + +if [ "$op" == "add" ] +then + ovs-ofctl add-flow $br priority=120,dl_src=$vm_mac,dl_dst=$dhcp_mac,actions=NORMAL + ovs-ofctl add-flow $br priority=80,udp,dl_src=$vm_mac,nw_dst=255.255.255.255,tp_dst=67,actions=NORMAL +else + ovs-ofctl del-flows --strict $br priority=120,dl_src=$vm_mac,dl_dst=$dhcp_mac + ovs-ofctl del-flows --strict $br priority=80,udp,dl_src=$vm_mac,nw_dst=255.255.255.255,tp_dst=67 +fi diff --git a/scripts/vm/network/ovs-pvlan-vm.sh b/scripts/vm/network/ovs-pvlan-vm.sh new file mode 100755 index 00000000000..8ac20df5ad1 --- /dev/null +++ b/scripts/vm/network/ovs-pvlan-vm.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +usage() { + printf "Usage: %s: (-A|-D) -b -p -i -d -m -v -h \n" $(basename $0) >&2 + exit 2 +} + +br= +pri_vlan= +sec_iso_vlan= +dhcp_ip= +dhcp_mac= +vm_mac= +op= + +while getopts 'ADb:p:i:d:m:v:h' OPTION +do + case $OPTION in + A) op="add" + ;; + D) op="del" + ;; + b) br="$OPTARG" + ;; + p) pri_vlan="$OPTARG" + ;; + i) sec_iso_vlan="$OPTARG" + ;; + d) dhcp_ip="$OPTARG" + ;; + m) dhcp_mac="$OPTARG" + ;; + v) vm_mac="$OPTARG" + ;; + h) usage + exit 1 + ;; + esac +done + +if [ -z "$op" ] +then + echo Missing operation pararmeter! + exit 1 +fi + +if [ -z "$br" ] +then + echo Missing parameter bridge! + exit 1 +fi + +if [ -z "$vm_mac" ] +then + echo Missing parameter VM MAC! + exit 1 +fi + +if [ -z "$sec_iso_vlan" ] +then + echo Missing parameter secondary isolate vlan! + exit 1 +fi + +trunk_port=1 + +if [ "$op" == "add" ] +then + ovs-ofctl add-flow $br priority=50,dl_src=$vm_mac,actions=mod_vlan_vid:$sec_iso_vlan,output:$trunk_port +else + # it would delete any rule related to this vm, not only the rule added above + ovs-ofctl del-flows $br dl_src=$vm_mac +fi + diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index f601f4fa2e4..d9c43567d06 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -31,6 +31,7 @@ import org.apache.cloudstack.api.command.admin.router.CreateVirtualRouterElement import org.apache.cloudstack.api.command.admin.router.ListVirtualRouterElementsCmd; import org.apache.log4j.Logger; +import com.cloud.agent.api.PvlanSetupCommand; import com.cloud.agent.api.to.LoadBalancerTO; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; @@ -48,6 +49,7 @@ import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.NetworkModel; +import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.PublicIpAddress; @@ -214,6 +216,15 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl DataCenter.class, network.getDataCenterId()); } + // Setup PVlan for vm if necessary + if (network.getTrafficType() == TrafficType.Guest && network.getBroadcastDomainType() == BroadcastDomainType.Pvlan) { + assert routers.size() == 1; + DomainRouterVO router = routers.get(0); + if (router.getHostId() == dest.getHost().getId()) { + _routerMgr.setupVmWithDhcpHostForPvlan(true, router, nic); + } + } + return true; } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java index f49ab79b500..4dfd78c2a52 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java @@ -19,6 +19,7 @@ package com.cloud.network.router; import java.util.List; import java.util.Map; +import com.cloud.agent.api.PvlanSetupCommand; import com.cloud.deploy.DeployDestination; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -35,6 +36,7 @@ import com.cloud.user.User; import com.cloud.uservm.UserVm; import com.cloud.utils.component.Manager; import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.Nic; import com.cloud.vm.NicProfile; import com.cloud.vm.VirtualMachineProfile; @@ -103,4 +105,6 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA boolean applyUserData(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, List routers) throws ResourceUnavailableException; + + void setupVmWithDhcpHostForPvlan(boolean add, DomainRouterVO router, NicProfile profile) throws ResourceUnavailableException; } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 6620e0a6379..bb31e1cf5e8 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -62,6 +62,7 @@ import com.cloud.agent.api.GetDomRVersionCmd; import com.cloud.agent.api.ModifySshKeysCommand; import com.cloud.agent.api.NetworkUsageAnswer; import com.cloud.agent.api.NetworkUsageCommand; +import com.cloud.agent.api.PvlanSetupCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.check.CheckSshAnswer; @@ -2210,6 +2211,72 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V return dhcpRange; } + private boolean setupDhcpForPvlanOnHost(boolean add, DomainRouterVO router, Nic routerNic) { + if (!routerNic.getBroadcastUri().getScheme().equals("pvlan")) { + return false; + } + setupDhcpForPvlan(add, router, routerNic); + Long hostId = router.getHostId(); + List vms = _userVmDao.listByHostId(hostId); + for (UserVmVO vm : vms) { + if (vm.getState() != State.Running) { + continue; + } + List nics = _nicDao.listByVmId(vm.getId()); + for (NicVO nic : nics) { + if (nic.getNetworkId() == routerNic.getNetworkId()) { + try { + Network network = _networkDao.findById(routerNic.getNetworkId()); + NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), + null, _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vm.getHypervisorType(), network)); + setupVmWithDhcpHostForPvlan(add, router, profile); + } catch (ResourceUnavailableException e) { + s_logger.warn("Fail to program pvlan on nic " + nic.getMacAddress(), e); + return false; + } + } + } + } + return true; + } + + private boolean setupDhcpForPvlan(boolean add, DomainRouterVO router, Nic nic) { + if (!nic.getBroadcastUri().getScheme().equals("pvlan")) { + return false; + } + String op = "add"; + if (!add) { + op = "delete"; + } + PvlanSetupCommand cmd = PvlanSetupCommand.createDhcpSetup(op, "xenbr0", nic.getBroadcastUri(), nic.getMacAddress(), nic.getIp4Address()); + Commands cmds = new Commands(cmd); + // In fact we send command to the host of router, we're not programming router but the host + try { + sendCommandsToRouter(router, cmds); + } catch (AgentUnavailableException e) { + s_logger.warn("Agent Unavailable ", e); + return false; + } + return true; + } + + @Override + public void setupVmWithDhcpHostForPvlan(boolean add, DomainRouterVO router, NicProfile profile) throws ResourceUnavailableException + { + if (!profile.getBroadCastUri().getScheme().equals("pvlan")) { + return; + } + String op = "add"; + if (!add) { + op = "delete"; + } + NicVO routerNic = _nicDao.findByInstanceIdAndNetworkId(profile.getNetworkId(), router.getId()); + PvlanSetupCommand cmd = PvlanSetupCommand.createVmInDhcpHostSetup(op, "xenbr0", profile.getBroadCastUri(), routerNic.getMacAddress(), profile.getMacAddress()); + Commands cmds = new Commands(cmd); + // In fact we send command to the host of router, we're not programming router but the host + sendCommandsToRouter(router, cmds); + } + @Override public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException { @@ -2505,11 +2572,18 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V List guestNetworks = new ArrayList(); List routerNics = _nicDao.listByVmId(profile.getId()); - for (Nic routerNic : routerNics) { - Network network = _networkModel.getNetwork(routerNic.getNetworkId()); + for (Nic nic : routerNics) { + Network network = _networkModel.getNetwork(nic.getNetworkId()); if (network.getTrafficType() == TrafficType.Guest) { guestNetworks.add(network); - } + if (nic.getBroadcastUri().getScheme().equals("pvlan")) { + result = setupDhcpForPvlanOnHost(true, router, nic); + } + } + } + + if (!result) { + return result; } answer = cmds.getAnswer("getDomRVersion"); @@ -2537,6 +2611,13 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V VMInstanceVO vm = profile.getVirtualMachine(); DomainRouterVO domR = _routerDao.findById(vm.getId()); processStopOrRebootAnswer(domR, answer); + List routerNics = _nicDao.listByVmId(profile.getId()); + for (Nic nic : routerNics) { + Network network = _networkModel.getNetwork(nic.getNetworkId()); + if (network.getTrafficType() == TrafficType.Guest && nic.getBroadcastUri().getScheme().equals("pvlan")) { + setupDhcpForPvlanOnHost(false, domR, nic); + } + } } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 8f2d103d343..7a9fc4731e7 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -69,6 +69,7 @@ import com.cloud.agent.api.GetVmStatsAnswer; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.PlugNicAnswer; import com.cloud.agent.api.PlugNicCommand; +import com.cloud.agent.api.PvlanSetupCommand; import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.UnPlugNicAnswer; @@ -2751,6 +2752,34 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use return true; } + private boolean setupVmForPvlan(boolean add, Long hostId, NicVO nic) { + if (!nic.getBroadcastUri().getScheme().equals("pvlan")) { + return false; + } + String op = "add"; + if (!add) { + // "delete" would remove all the rules(if using ovs) related to this vm + op = "delete"; + } + PvlanSetupCommand cmd = PvlanSetupCommand.createVmSetup(op, "xenbr0", nic.getBroadcastUri(), nic.getMacAddress()); + Answer answer = null; + try { + answer = _agentMgr.send(hostId, cmd); + } catch (OperationTimedoutException e) { + s_logger.warn("Timed Out", e); + return false; + } catch (AgentUnavailableException e) { + s_logger.warn("Agent Unavailable ", e); + return false; + } + + boolean result = true; + if (answer == null || !answer.getResult()) { + result = false; + } + return result; + } + @Override public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, @@ -2812,6 +2841,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use originalIp = nic.getIp4Address(); guestNic = nic; guestNetwork = network; + if (nic.getBroadcastUri().getScheme().equals("pvlan")) { + if (!setupVmForPvlan(true, hostId, nic)) { + return false; + } + } } } boolean ipChanged = false; @@ -2942,6 +2976,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use + " stop due to exception ", ex); } } + + VMInstanceVO vm = profile.getVirtualMachine(); + List nics = _nicDao.listByVmId(vm.getId()); + for (NicVO nic : nics) { + NetworkVO network = _networkDao.findById(nic.getNetworkId()); + if (network.getTrafficType() == TrafficType.Guest) { + if (nic.getBroadcastUri().getScheme().equals("pvlan")) { + setupVmForPvlan(false, vm.getHostId(), nic); + } + } + } } public String generateRandomPassword() { diff --git a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java index ef5478bb1f8..5278b339e19 100644 --- a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java +++ b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java @@ -402,4 +402,11 @@ VpcVirtualNetworkApplianceService { return null; } + @Override + public void setupVmWithDhcpHostForPvlan(boolean add, + DomainRouterVO router, NicProfile nic) throws ResourceUnavailableException { + // TODO Auto-generated method stub + + } + } From 05885457ecc32e4714914056c11244e0d021bf50 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Wed, 1 May 2013 13:23:08 -0700 Subject: [PATCH 03/36] PVLAN: Simplify OVS policy We can resubmit the packet against the flow table to get simplier result. Now we don't need to check if VM is in the same host as DHCP server or not. --- .../cloud/agent/api/PvlanSetupCommand.java | 25 ++---- .../xen/resource/CitrixResourceBase.java | 18 ++-- .../hypervisor/xenserver/ovs-get-dhcp-port.sh | 26 ++++++ scripts/vm/hypervisor/xenserver/ovs-pvlan | 68 ++++---------- .../vm/hypervisor/xenserver/xenserver60/patch | 2 +- scripts/vm/network/ovs-pvlan-dhcp-host.sh | 34 +++++-- .../vm/network/ovs-pvlan-vm-in-dhcp-host.sh | 88 ------------------- scripts/vm/network/ovs-pvlan-vm.sh | 15 +++- .../network/element/VirtualRouterElement.java | 10 --- .../VirtualNetworkApplianceManager.java | 2 - .../VirtualNetworkApplianceManagerImpl.java | 53 +---------- ...MockVpcVirtualNetworkApplianceManager.java | 8 -- 12 files changed, 104 insertions(+), 245 deletions(-) create mode 100644 scripts/vm/hypervisor/xenserver/ovs-get-dhcp-port.sh delete mode 100755 scripts/vm/network/ovs-pvlan-vm-in-dhcp-host.sh diff --git a/api/src/com/cloud/agent/api/PvlanSetupCommand.java b/api/src/com/cloud/agent/api/PvlanSetupCommand.java index 22a828afa8b..e5d4da09003 100644 --- a/api/src/com/cloud/agent/api/PvlanSetupCommand.java +++ b/api/src/com/cloud/agent/api/PvlanSetupCommand.java @@ -23,17 +23,16 @@ import com.cloud.utils.net.NetUtils; public class PvlanSetupCommand extends Command { public enum Type { DHCP, - VM, - VM_IN_DHCP_HOST + VM } private String op; private String bridge; private String primary; private String isolated; private String vmMac; + private String dhcpName; private String dhcpMac; private String dhcpIp; - private boolean strict; private Type type; protected PvlanSetupCommand() {} @@ -45,12 +44,12 @@ public class PvlanSetupCommand extends Command { this.bridge = bridge; this.primary = NetUtils.getPrimaryPvlanFromUri(uri); this.isolated = NetUtils.getIsolatedPvlanFromUri(uri); - this.strict = true; } - static public PvlanSetupCommand createDhcpSetup(String op, String bridge, URI uri, String dhcpMac, String dhcpIp) + static public PvlanSetupCommand createDhcpSetup(String op, String bridge, URI uri, String dhcpName, String dhcpMac, String dhcpIp) { PvlanSetupCommand cmd = new PvlanSetupCommand(Type.DHCP, op, bridge, uri); + cmd.setDhcpName(dhcpName); cmd.setDhcpMac(dhcpMac); cmd.setDhcpIp(dhcpIp); return cmd; @@ -63,14 +62,6 @@ public class PvlanSetupCommand extends Command { return cmd; } - static public PvlanSetupCommand createVmInDhcpHostSetup(String op, String bridge, URI uri, String dhcpMac, String vmMac) - { - PvlanSetupCommand cmd = new PvlanSetupCommand(Type.VM_IN_DHCP_HOST, op, bridge, uri); - cmd.setDhcpMac(dhcpMac); - cmd.setVmMac(vmMac); - return cmd; - } - @Override public boolean executeInSequence() { return true; @@ -120,11 +111,11 @@ public class PvlanSetupCommand extends Command { return type; } - public boolean isStrict() { - return strict; + public String getDhcpName() { + return dhcpName; } - public void setStrict(boolean strict) { - this.strict = strict; + public void setDhcpName(String dhcpName) { + this.dhcpName = dhcpName; } } diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 34b590e40c9..933f4d33eff 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -1475,13 +1475,16 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String isolatedPvlan = cmd.getIsolated(); String op = cmd.getOp(); String bridge = cmd.getBridge(); - String result = null; + String dhcpName = cmd.getDhcpName(); String dhcpMac = cmd.getDhcpMac(); String dhcpIp = cmd.getDhcpIp(); String vmMac = cmd.getVmMac(); + + String result = null; if (cmd.getType() == PvlanSetupCommand.Type.DHCP) { result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-dhcp", "op", op, "bridge", bridge, - "primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, "dhcp-ip", dhcpIp, "dhcp-mac", dhcpMac); + "primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, "dhcp-name", dhcpName, + "dhcp-ip", dhcpIp, "dhcp-mac", dhcpMac); if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { s_logger.warn("Failed to program pvlan for dhcp server with mac " + dhcpMac); return new Answer(cmd, false, result); @@ -1489,7 +1492,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.info("Programmed pvlan for dhcp server with mac " + dhcpMac); } } else if (cmd.getType() == PvlanSetupCommand.Type.VM) { - result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-vm-alone", "op", op, "bridge", bridge, + result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-vm", "op", op, "bridge", bridge, "primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, "vm-mac", vmMac); if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { s_logger.warn("Failed to program pvlan for vm with mac " + vmMac); @@ -1497,15 +1500,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } else { s_logger.info("Programmed pvlan for vm with mac " + vmMac); } - } else if (cmd.getType() == PvlanSetupCommand.Type.VM_IN_DHCP_HOST) { - result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-vm-dhcp", "op", op, "bridge", bridge, - "primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, "vm-mac", vmMac, "dhcp-mac", dhcpMac); - if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { - s_logger.warn("Failed to program pvlan for vm in dhcp host with mac " + vmMac); - return new Answer(cmd, false, result); - } else { - s_logger.info("Programmed pvlan for vm in dhcp host with mac " + vmMac); - } } return new Answer(cmd, true, result); } diff --git a/scripts/vm/hypervisor/xenserver/ovs-get-dhcp-port.sh b/scripts/vm/hypervisor/xenserver/ovs-get-dhcp-port.sh new file mode 100644 index 00000000000..a30b180bed0 --- /dev/null +++ b/scripts/vm/hypervisor/xenserver/ovs-get-dhcp-port.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +#!/bin/bash + +bridge=$1 +dhcp_name=$2 +dom_id=`xe vm-list is-control-domain=false power-state=running params=dom-id name-label=$dhcp_name|cut -d ':' -f 2 |tr -d ' ' ` +iface="vif${dom_id}.0" +port=`ovs-ofctl show $bridge|grep $iface|cut -d '(' -f 1|tr -d ' '` +echo $port diff --git a/scripts/vm/hypervisor/xenserver/ovs-pvlan b/scripts/vm/hypervisor/xenserver/ovs-pvlan index 2c1e3af8f77..372d3c8d05b 100755 --- a/scripts/vm/hypervisor/xenserver/ovs-pvlan +++ b/scripts/vm/hypervisor/xenserver/ovs-pvlan @@ -33,8 +33,8 @@ from time import localtime as _localtime, asctime as _asctime xePath = "/opt/xensource/bin/xe" lib.setup_logging("/var/log/ovs-pvlan.log") dhcpSetupPath = "/opt/xensource/bin/ovs-pvlan-dhcp-host.sh" -vmAloneSetupPath = "/opt/xensource/bin/ovs-pvlan-vm.sh" -vmDhcpSetupPath = "/opt/xensource/bin/ovs-pvlan-vm-in-dhcp-host.sh" +vmSetupPath = "/opt/xensource/bin/ovs-pvlan-vm.sh" +getDhcpPortPath = "/opt/xensource/bin/ovs-get-dhcp-port.sh" pvlanCleanupPath = "/opt/xensource/bin/ovs-pvlan-cleanup.sh" def echo(fn): @@ -53,17 +53,21 @@ def setup_pvlan_dhcp(session, args): bridge = args.pop("bridge") primary = args.pop("primary-pvlan") isolated = args.pop("isolated-pvlan") - dhcp_ip = args.pop("dhcp-ip"); - dhcp_mac = args.pop("dhcp-mac"); + dhcp_name = args.pop("dhcp-name") + dhcp_ip = args.pop("dhcp-ip") + dhcp_mac = args.pop("dhcp-mac") res = lib.check_switch() if res != "SUCCESS": return "FAILURE:%s" % res if op == "add": + logging.debug("Try to get dhcp vm %s port on the switch:%s" % (dhcp_name, bridge)) + dhcp_port = lib.do_cmd([getDhcpPortPath, bridge, dhcp_name]) logging.debug("About to setup dhcp vm on the switch:%s" % bridge) res = lib.do_cmd([dhcpSetupPath, "-A", "-b", bridge, "-p", primary, - "-i", isolated, "-d", dhcp_ip, "-m", dhcp_mac]) + "-i", isolated, "-n", dhcp_name, "-d", dhcp_ip, "-m", dhcp_mac, + "-P", dhcp_port]) if res: result = "FAILURE:%s" % res return result; @@ -71,7 +75,7 @@ def setup_pvlan_dhcp(session, args): elif op == "delete": logging.debug("About to remove dhcp the switch:%s" % bridge) res = lib.do_cmd([dhcpSetupPath, "-D", "-b", bridge, "-p", primary, - "-i", isolated, "-d", dhcp_ip, "-m", dhcp_mac]) + "-i", isolated, "-n", dhcp_name, "-d", dhcp_ip, "-m", dhcp_mac]) if res: result = "FAILURE:%s" % res return result; @@ -82,9 +86,10 @@ def setup_pvlan_dhcp(session, args): return result @echo -def setup_pvlan_vm_alone(session, args): +def setup_pvlan_vm(session, args): op = args.pop("op") bridge = args.pop("bridge") + primary = args.pop("primary-pvlan") isolated = args.pop("isolated-pvlan") vm_mac = args.pop("vm-mac") trunk_port = 1 @@ -94,58 +99,24 @@ def setup_pvlan_vm_alone(session, args): return "FAILURE:%s" % res if op == "add": - logging.debug("About to setup vm alone on the switch:%s" % bridge) - res = lib.do_cmd([vmAloneSetupPath, "-A", "-b", bridge, "-i", isolated, "-v", vm_mac]) + logging.debug("About to setup vm on the switch:%s" % bridge) + res = lib.do_cmd([vmSetupPath, "-A", "-b", bridge, "-p", primary, "-i", isolated, "-v", vm_mac]) if res: result = "FAILURE:%s" % res return result; - logging.debug("Setup vm alone on switch program done") + logging.debug("Setup vm on switch program done") elif op == "delete": - logging.debug("About to remove vm alone on the switch:%s" % bridge) - res = lib.do_cmd([vmAloneSetupPath, "-D", "-b", bridge, "-i", isolated, "-v", vm_mac]) + logging.debug("About to remove vm on the switch:%s" % bridge) + res = lib.do_cmd([vmSetupPath, "-D", "-b", bridge, "-p", primary, "-i", isolated, "-v", vm_mac]) if res: result = "FAILURE:%s" % res return result; - logging.debug("Remove vm alone on switch program done") + logging.debug("Remove vm on switch program done") result = "true" logging.debug("Setup_pvlan_vm_alone completed with result:%s" % result) return result -@echo -def setup_pvlan_vm_dhcp(session, args): - op = args.pop("op") - bridge = args.pop("bridge") - isolated = args.pop("isolated-pvlan") - vm_mac = args.pop("vm-mac") - dhcp_mac = args.pop("dhcp-mac"); - trunk_port = 1 - - res = lib.check_switch() - if res != "SUCCESS": - return "FAILURE:%s" % res - - if op == "add": - logging.debug("About to setup vm dhcp on the switch:%s" % bridge) - res = lib.do_cmd([vmDhcpSetupPath, "-A", "-b", bridge, "-i", isolated, - "-v", vm_mac, "-m", dhcp_mac]) - if res: - result = "FAILURE:%s" % res - return result; - logging.debug("Setup vm dhcp on switch program done") - elif op == "delete": - logging.debug("About to remove vm dhcp on the switch:%s" % bridge) - res = lib.do_cmd([vmDhcpSetupPath, "-D", "-b", bridge, "-i", isolated, - "-v", vm_mac, "-m", dhcp_mac]) - if res: - result = "FAILURE:%s" % res - return result; - logging.debug("Remove vm dhcp on switch program done") - - result = "true" - logging.debug("Setup_pvlan_vm_dhcp completed with result:%s" % result) - return result - @echo def cleanup(session, args): res = lib.check_switch() @@ -163,6 +134,5 @@ def cleanup(session, args): if __name__ == "__main__": XenAPIPlugin.dispatch({"setup-pvlan-dhcp": setup_pvlan_dhcp, - "setup-pvlan-vm-alone": setup_pvlan_vm_alone, - "setup-pvlan-vm-dhcp": setup_pvlan_vm_dhcp, + "setup-pvlan-vm": setup_pvlan_vm, "cleanup":cleanup}) diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch index c767f1af7df..97595190904 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver60/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch @@ -69,6 +69,6 @@ swiftxen=..,0755,/etc/xapi.d/plugins s3xen=..,0755,/etc/xapi.d/plugins ovs-pvlan=..,0755,/etc/xapi.d/plugins ovs-pvlan-dhcp-host.sh=../../../network,0755,/opt/xensource/bin -ovs-pvlan-vm-in-dhcp-host.sh=../../../network,0755,/opt/xensource/bin ovs-pvlan-vm.sh=../../../network,0755,/opt/xensource/bin ovs-pvlan-cleanup.sh=../../../network,0755,/opt/xensource/bin +ovs-get-dhcp-port.sh=..,0755,/opt/xensource/bin diff --git a/scripts/vm/network/ovs-pvlan-dhcp-host.sh b/scripts/vm/network/ovs-pvlan-dhcp-host.sh index e12fbce0f18..93f56534beb 100755 --- a/scripts/vm/network/ovs-pvlan-dhcp-host.sh +++ b/scripts/vm/network/ovs-pvlan-dhcp-host.sh @@ -16,20 +16,26 @@ # specific language governing permissions and limitations # under the License. +#!/bin/bash + +source ovs-func.sh + usage() { - printf "Usage: %s: (-A|-D) -b -p -i -d -m -v -h \n" $(basename $0) >&2 + printf "Usage: %s: (-A|-D) -b -p -i -n -d -m -P -v -h \n" $(basename $0) >&2 exit 2 } br= pri_vlan= sec_iso_vlan= +dhcp_name= dhcp_ip= dhcp_mac= +dhcp_port= vm_mac= op= -while getopts 'ADb:p:i:d:m:v:h' OPTION +while getopts 'ADb:p:i:d:m:v:n:P:h' OPTION do case $OPTION in A) op="add" @@ -42,10 +48,14 @@ do ;; i) sec_iso_vlan="$OPTARG" ;; + n) dhcp_name="$OPTARG" + ;; d) dhcp_ip="$OPTARG" ;; m) dhcp_mac="$OPTARG" ;; + P) dhcp_port="$OPTARG" + ;; v) vm_mac="$OPTARG" ;; h) usage @@ -78,6 +88,12 @@ then exit 1 fi +if [ -z "$dhcp_name" ] +then + echo Missing parameter DHCP NAME! + exit 1 +fi + if [ -z "$dhcp_ip" ] then echo Missing parameter DHCP IP! @@ -90,12 +106,18 @@ then exit 1 fi +if [ "$op" == "add" -a -z "$dhcp_port" ] +then + echo Missing parameter DHCP PORT! + exit 1 +fi + if [ "$op" == "add" ] then - ovs-ofctl add-flow $br priority=200,arp,dl_vlan=$sec_iso_vlan,nw_dst=$dhcp_ip,actions=mod_vlan_vid:$pri_vlan,NORMAL - ovs-ofctl add-flow $br priority=180,arp,nw_dst=$dhcp_ip,actions=NORMAL - ovs-ofctl add-flow $br priority=150,dl_vlan=$sec_iso_vlan,dl_dst=$dhcp_mac,actions=mod_vlan_vid:$pri_vlan,NORMAL - ovs-ofctl add-flow $br priority=100,udp,dl_vlan=$sec_iso_vlan,nw_dst=255.255.255.255,tp_dst=67,actions=mod_vlan_vid:$pri_vlan,NORMAL + ovs-ofctl add-flow $br priority=200,arp,dl_vlan=$sec_iso_vlan,nw_dst=$dhcp_ip,actions=strip_vlan,output:$dhcp_port + ovs-ofctl add-flow $br priority=180,arp,nw_dst=$dhcp_ip,actions=strip_vlan,output:$dhcp_port + ovs-ofctl add-flow $br priority=150,dl_vlan=$sec_iso_vlan,dl_dst=$dhcp_mac,actions=strip_vlan,output:$dhcp_port + ovs-ofctl add-flow $br priority=100,udp,dl_vlan=$sec_iso_vlan,nw_dst=255.255.255.255,tp_dst=67,actions=strip_vlan,output:$dhcp_port else ovs-ofctl del-flows --strict $br priority=200,arp,dl_vlan=$sec_iso_vlan,nw_dst=$dhcp_ip ovs-ofctl del-flows --strict $br priority=180,arp,nw_dst=$dhcp_ip diff --git a/scripts/vm/network/ovs-pvlan-vm-in-dhcp-host.sh b/scripts/vm/network/ovs-pvlan-vm-in-dhcp-host.sh deleted file mode 100755 index de37882159c..00000000000 --- a/scripts/vm/network/ovs-pvlan-vm-in-dhcp-host.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/bash -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -usage() { - printf "Usage: %s: (-A|-D) -b -p -i -d -m -v -h \n" $(basename $0) >&2 - exit 2 -} - -br= -pri_vlan= -sec_iso_vlan= -dhcp_ip= -dhcp_mac= -vm_mac= -op= - -while getopts 'ADb:p:i:d:m:v:h' OPTION -do - case $OPTION in - A) op="add" - ;; - D) op="del" - ;; - b) br="$OPTARG" - ;; - p) pri_vlan="$OPTARG" - ;; - i) sec_iso_vlan="$OPTARG" - ;; - d) dhcp_ip="$OPTARG" - ;; - m) dhcp_mac="$OPTARG" - ;; - v) vm_mac="$OPTARG" - ;; - h) usage - exit 1 - ;; - esac -done - -if [ -z "$op" ] -then - echo Missing operation pararmeter! - exit 1 -fi - -if [ -z "$br" ] -then - echo Missing parameter bridge! - exit 1 -fi - -if [ -z "$vm_mac" ] -then - echo Missing parameter VM MAC! - exit 1 -fi - -if [ -z "$dhcp_mac" ] -then - echo Missing parameter DHCP MAC! - exit 1 -fi - -if [ "$op" == "add" ] -then - ovs-ofctl add-flow $br priority=120,dl_src=$vm_mac,dl_dst=$dhcp_mac,actions=NORMAL - ovs-ofctl add-flow $br priority=80,udp,dl_src=$vm_mac,nw_dst=255.255.255.255,tp_dst=67,actions=NORMAL -else - ovs-ofctl del-flows --strict $br priority=120,dl_src=$vm_mac,dl_dst=$dhcp_mac - ovs-ofctl del-flows --strict $br priority=80,udp,dl_src=$vm_mac,nw_dst=255.255.255.255,tp_dst=67 -fi diff --git a/scripts/vm/network/ovs-pvlan-vm.sh b/scripts/vm/network/ovs-pvlan-vm.sh index 8ac20df5ad1..4bad11c7624 100755 --- a/scripts/vm/network/ovs-pvlan-vm.sh +++ b/scripts/vm/network/ovs-pvlan-vm.sh @@ -16,6 +16,8 @@ # specific language governing permissions and limitations # under the License. +#!/bin/bash + usage() { printf "Usage: %s: (-A|-D) -b -p -i -d -m -v -h \n" $(basename $0) >&2 exit 2 @@ -72,6 +74,12 @@ then exit 1 fi +if [ -z "$pri_vlan" ] +then + echo Missing parameter secondary isolate vlan! + exit 1 +fi + if [ -z "$sec_iso_vlan" ] then echo Missing parameter secondary isolate vlan! @@ -82,9 +90,10 @@ trunk_port=1 if [ "$op" == "add" ] then - ovs-ofctl add-flow $br priority=50,dl_src=$vm_mac,actions=mod_vlan_vid:$sec_iso_vlan,output:$trunk_port + ovs-ofctl add-flow $br priority=50,dl_vlan=0xffff,dl_src=$vm_mac,actions=mod_vlan_vid:$sec_iso_vlan,resubmit:$trunk_port + ovs-ofctl add-flow $br priority=60,dl_vlan=$sec_iso_vlan,dl_src=$vm_mac,actions=output:1 else - # it would delete any rule related to this vm, not only the rule added above - ovs-ofctl del-flows $br dl_src=$vm_mac + ovs-ofctl del-flows --strict $br priority=50,dl_vlan=0xffff,dl_src=$vm_mac + ovs-ofctl del-flows --strict $br priority=60,dl_vlan=$sec_iso_vlan,dl_src=$vm_mac fi diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index d9c43567d06..5c73bcdd80e 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -215,16 +215,6 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl throw new ResourceUnavailableException("Can't find at least one running router!", DataCenter.class, network.getDataCenterId()); } - - // Setup PVlan for vm if necessary - if (network.getTrafficType() == TrafficType.Guest && network.getBroadcastDomainType() == BroadcastDomainType.Pvlan) { - assert routers.size() == 1; - DomainRouterVO router = routers.get(0); - if (router.getHostId() == dest.getHost().getId()) { - _routerMgr.setupVmWithDhcpHostForPvlan(true, router, nic); - } - } - return true; } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java index 4dfd78c2a52..075b014cb0b 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java @@ -105,6 +105,4 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA boolean applyUserData(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, List routers) throws ResourceUnavailableException; - - void setupVmWithDhcpHostForPvlan(boolean add, DomainRouterVO router, NicProfile profile) throws ResourceUnavailableException; } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index bb31e1cf5e8..d22c7fc6d31 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -2211,35 +2211,6 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V return dhcpRange; } - private boolean setupDhcpForPvlanOnHost(boolean add, DomainRouterVO router, Nic routerNic) { - if (!routerNic.getBroadcastUri().getScheme().equals("pvlan")) { - return false; - } - setupDhcpForPvlan(add, router, routerNic); - Long hostId = router.getHostId(); - List vms = _userVmDao.listByHostId(hostId); - for (UserVmVO vm : vms) { - if (vm.getState() != State.Running) { - continue; - } - List nics = _nicDao.listByVmId(vm.getId()); - for (NicVO nic : nics) { - if (nic.getNetworkId() == routerNic.getNetworkId()) { - try { - Network network = _networkDao.findById(routerNic.getNetworkId()); - NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), - null, _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vm.getHypervisorType(), network)); - setupVmWithDhcpHostForPvlan(add, router, profile); - } catch (ResourceUnavailableException e) { - s_logger.warn("Fail to program pvlan on nic " + nic.getMacAddress(), e); - return false; - } - } - } - } - return true; - } - private boolean setupDhcpForPvlan(boolean add, DomainRouterVO router, Nic nic) { if (!nic.getBroadcastUri().getScheme().equals("pvlan")) { return false; @@ -2248,7 +2219,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V if (!add) { op = "delete"; } - PvlanSetupCommand cmd = PvlanSetupCommand.createDhcpSetup(op, "xenbr0", nic.getBroadcastUri(), nic.getMacAddress(), nic.getIp4Address()); + PvlanSetupCommand cmd = PvlanSetupCommand.createDhcpSetup(op, "xenbr0", nic.getBroadcastUri(), router.getInstanceName(), nic.getMacAddress(), nic.getIp4Address()); Commands cmds = new Commands(cmd); // In fact we send command to the host of router, we're not programming router but the host try { @@ -2260,23 +2231,6 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V return true; } - @Override - public void setupVmWithDhcpHostForPvlan(boolean add, DomainRouterVO router, NicProfile profile) throws ResourceUnavailableException - { - if (!profile.getBroadCastUri().getScheme().equals("pvlan")) { - return; - } - String op = "add"; - if (!add) { - op = "delete"; - } - NicVO routerNic = _nicDao.findByInstanceIdAndNetworkId(profile.getNetworkId(), router.getId()); - PvlanSetupCommand cmd = PvlanSetupCommand.createVmInDhcpHostSetup(op, "xenbr0", profile.getBroadCastUri(), routerNic.getMacAddress(), profile.getMacAddress()); - Commands cmds = new Commands(cmd); - // In fact we send command to the host of router, we're not programming router but the host - sendCommandsToRouter(router, cmds); - } - @Override public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException { @@ -2577,7 +2531,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V if (network.getTrafficType() == TrafficType.Guest) { guestNetworks.add(network); if (nic.getBroadcastUri().getScheme().equals("pvlan")) { - result = setupDhcpForPvlanOnHost(true, router, nic); + result = setupDhcpForPvlan(true, router, nic); } } } @@ -2615,9 +2569,10 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V for (Nic nic : routerNics) { Network network = _networkModel.getNetwork(nic.getNetworkId()); if (network.getTrafficType() == TrafficType.Guest && nic.getBroadcastUri().getScheme().equals("pvlan")) { - setupDhcpForPvlanOnHost(false, domR, nic); + setupDhcpForPvlan(false, domR, nic); } } + } } diff --git a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java index 5278b339e19..e86fc09ce2c 100644 --- a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java +++ b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java @@ -401,12 +401,4 @@ VpcVirtualNetworkApplianceService { // TODO Auto-generated method stub return null; } - - @Override - public void setupVmWithDhcpHostForPvlan(boolean add, - DomainRouterVO router, NicProfile nic) throws ResourceUnavailableException { - // TODO Auto-generated method stub - - } - } From 142f3b30f44f279b34ce845ffaec853ef68be36d Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Wed, 1 May 2013 13:23:08 -0700 Subject: [PATCH 04/36] PVLAN: Remove bridge parameter in PvlanSetupCommand Bridge is hypervisor dependent, shouldn't appear in PvlanSetupCommand. --- .../com/cloud/agent/api/PvlanSetupCommand.java | 16 +++++----------- .../xen/resource/CitrixResourceBase.java | 2 +- .../VirtualNetworkApplianceManagerImpl.java | 2 +- server/src/com/cloud/vm/UserVmManagerImpl.java | 2 +- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/api/src/com/cloud/agent/api/PvlanSetupCommand.java b/api/src/com/cloud/agent/api/PvlanSetupCommand.java index e5d4da09003..0426219def2 100644 --- a/api/src/com/cloud/agent/api/PvlanSetupCommand.java +++ b/api/src/com/cloud/agent/api/PvlanSetupCommand.java @@ -26,7 +26,6 @@ public class PvlanSetupCommand extends Command { VM } private String op; - private String bridge; private String primary; private String isolated; private String vmMac; @@ -37,27 +36,26 @@ public class PvlanSetupCommand extends Command { protected PvlanSetupCommand() {} - protected PvlanSetupCommand(Type type, String op, String bridge, URI uri) + protected PvlanSetupCommand(Type type, String op, URI uri) { this.type = type; this.op = op; - this.bridge = bridge; this.primary = NetUtils.getPrimaryPvlanFromUri(uri); this.isolated = NetUtils.getIsolatedPvlanFromUri(uri); } - static public PvlanSetupCommand createDhcpSetup(String op, String bridge, URI uri, String dhcpName, String dhcpMac, String dhcpIp) + static public PvlanSetupCommand createDhcpSetup(String op, URI uri, String dhcpName, String dhcpMac, String dhcpIp) { - PvlanSetupCommand cmd = new PvlanSetupCommand(Type.DHCP, op, bridge, uri); + PvlanSetupCommand cmd = new PvlanSetupCommand(Type.DHCP, op, uri); cmd.setDhcpName(dhcpName); cmd.setDhcpMac(dhcpMac); cmd.setDhcpIp(dhcpIp); return cmd; } - static public PvlanSetupCommand createVmSetup(String op, String bridge, URI uri, String vmMac) + static public PvlanSetupCommand createVmSetup(String op, URI uri, String vmMac) { - PvlanSetupCommand cmd = new PvlanSetupCommand(Type.VM, op, bridge, uri); + PvlanSetupCommand cmd = new PvlanSetupCommand(Type.VM, op, uri); cmd.setVmMac(vmMac); return cmd; } @@ -71,10 +69,6 @@ public class PvlanSetupCommand extends Command { return op; } - public String getBridge() { - return bridge; - } - public String getPrimary() { return primary; } diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 933f4d33eff..d25938f1f57 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -1474,12 +1474,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String primaryPvlan = cmd.getPrimary(); String isolatedPvlan = cmd.getIsolated(); String op = cmd.getOp(); - String bridge = cmd.getBridge(); String dhcpName = cmd.getDhcpName(); String dhcpMac = cmd.getDhcpMac(); String dhcpIp = cmd.getDhcpIp(); String vmMac = cmd.getVmMac(); + String bridge = "xenbr0"; String result = null; if (cmd.getType() == PvlanSetupCommand.Type.DHCP) { result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-dhcp", "op", op, "bridge", bridge, diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index d22c7fc6d31..59a9f057162 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -2219,7 +2219,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V if (!add) { op = "delete"; } - PvlanSetupCommand cmd = PvlanSetupCommand.createDhcpSetup(op, "xenbr0", nic.getBroadcastUri(), router.getInstanceName(), nic.getMacAddress(), nic.getIp4Address()); + PvlanSetupCommand cmd = PvlanSetupCommand.createDhcpSetup(op, nic.getBroadcastUri(), router.getInstanceName(), nic.getMacAddress(), nic.getIp4Address()); Commands cmds = new Commands(cmd); // In fact we send command to the host of router, we're not programming router but the host try { diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 7a9fc4731e7..6ea295259a9 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2761,7 +2761,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use // "delete" would remove all the rules(if using ovs) related to this vm op = "delete"; } - PvlanSetupCommand cmd = PvlanSetupCommand.createVmSetup(op, "xenbr0", nic.getBroadcastUri(), nic.getMacAddress()); + PvlanSetupCommand cmd = PvlanSetupCommand.createVmSetup(op, nic.getBroadcastUri(), nic.getMacAddress()); Answer answer = null; try { answer = _agentMgr.send(hostId, cmd); From 40386fc4cb6841c8cc6b8458c9ebd80d4c8ffb4f Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Wed, 1 May 2013 13:23:09 -0700 Subject: [PATCH 05/36] PVLAN: Add network label parameter to PvlanSetupCommand We need it to find the real bridge/switch to program on the OVS. --- .../cloud/agent/api/PvlanSetupCommand.java | 16 +++++++---- .../xen/resource/CitrixResourceBase.java | 19 ++++++++++--- .../vm/hypervisor/xenserver/ovs-get-bridge.sh | 27 +++++++++++++++++++ .../hypervisor/xenserver/ovs-get-dhcp-port.sh | 0 scripts/vm/hypervisor/xenserver/ovs-pvlan | 13 ++++++--- .../vm/hypervisor/xenserver/xenserver60/patch | 1 + .../VirtualNetworkApplianceManagerImpl.java | 4 ++- .../src/com/cloud/vm/UserVmManagerImpl.java | 5 +++- 8 files changed, 72 insertions(+), 13 deletions(-) create mode 100755 scripts/vm/hypervisor/xenserver/ovs-get-bridge.sh mode change 100644 => 100755 scripts/vm/hypervisor/xenserver/ovs-get-dhcp-port.sh diff --git a/api/src/com/cloud/agent/api/PvlanSetupCommand.java b/api/src/com/cloud/agent/api/PvlanSetupCommand.java index 0426219def2..ee1f046d6d9 100644 --- a/api/src/com/cloud/agent/api/PvlanSetupCommand.java +++ b/api/src/com/cloud/agent/api/PvlanSetupCommand.java @@ -33,29 +33,31 @@ public class PvlanSetupCommand extends Command { private String dhcpMac; private String dhcpIp; private Type type; + private String networkTag; protected PvlanSetupCommand() {} - protected PvlanSetupCommand(Type type, String op, URI uri) + protected PvlanSetupCommand(Type type, String op, URI uri, String networkTag) { this.type = type; this.op = op; this.primary = NetUtils.getPrimaryPvlanFromUri(uri); this.isolated = NetUtils.getIsolatedPvlanFromUri(uri); + this.networkTag = networkTag; } - static public PvlanSetupCommand createDhcpSetup(String op, URI uri, String dhcpName, String dhcpMac, String dhcpIp) + static public PvlanSetupCommand createDhcpSetup(String op, URI uri, String networkTag, String dhcpName, String dhcpMac, String dhcpIp) { - PvlanSetupCommand cmd = new PvlanSetupCommand(Type.DHCP, op, uri); + PvlanSetupCommand cmd = new PvlanSetupCommand(Type.DHCP, op, uri, networkTag); cmd.setDhcpName(dhcpName); cmd.setDhcpMac(dhcpMac); cmd.setDhcpIp(dhcpIp); return cmd; } - static public PvlanSetupCommand createVmSetup(String op, URI uri, String vmMac) + static public PvlanSetupCommand createVmSetup(String op, URI uri, String networkTag, String vmMac) { - PvlanSetupCommand cmd = new PvlanSetupCommand(Type.VM, op, uri); + PvlanSetupCommand cmd = new PvlanSetupCommand(Type.VM, op, uri, networkTag); cmd.setVmMac(vmMac); return cmd; } @@ -112,4 +114,8 @@ public class PvlanSetupCommand extends Command { public void setDhcpName(String dhcpName) { this.dhcpName = dhcpName; } + + public String getNetworkTag() { + return networkTag; + } } diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index d25938f1f57..d616e1bcd58 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -1478,11 +1478,24 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String dhcpMac = cmd.getDhcpMac(); String dhcpIp = cmd.getDhcpIp(); String vmMac = cmd.getVmMac(); + String networkTag = cmd.getNetworkTag(); + + XsLocalNetwork nw = null; + String nwNameLabel = null; + try { + nw = getNativeNetworkForTraffic(conn, TrafficType.Guest, networkTag); + nwNameLabel = nw.getNetwork().getNameLabel(conn); + } catch (XenAPIException e) { + s_logger.warn("Fail to get network", e); + return new Answer(cmd, false, e.toString()); + } catch (XmlRpcException e) { + s_logger.warn("Fail to get network", e); + return new Answer(cmd, false, e.toString()); + } - String bridge = "xenbr0"; String result = null; if (cmd.getType() == PvlanSetupCommand.Type.DHCP) { - result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-dhcp", "op", op, "bridge", bridge, + result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-dhcp", "op", op, "nw-label", nwNameLabel, "primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, "dhcp-name", dhcpName, "dhcp-ip", dhcpIp, "dhcp-mac", dhcpMac); if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { @@ -1492,7 +1505,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.info("Programmed pvlan for dhcp server with mac " + dhcpMac); } } else if (cmd.getType() == PvlanSetupCommand.Type.VM) { - result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-vm", "op", op, "bridge", bridge, + result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-vm", "op", op, "nw-label", nwNameLabel, "primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, "vm-mac", vmMac); if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { s_logger.warn("Failed to program pvlan for vm with mac " + vmMac); diff --git a/scripts/vm/hypervisor/xenserver/ovs-get-bridge.sh b/scripts/vm/hypervisor/xenserver/ovs-get-bridge.sh new file mode 100755 index 00000000000..f56ddf9020f --- /dev/null +++ b/scripts/vm/hypervisor/xenserver/ovs-get-bridge.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +nw_label=$1 +br=`xe network-list name-label="$nw_label" params=bridge |cut -d ':' -f 2 |tr -d ' ' ` +pbr=`ovs-vsctl br-to-parent $br` +while [ "$br" != "$pbr" ] +do + br=$pbr + pbr=`ovs-vsctl br-to-parent $br` +done +echo $pbr diff --git a/scripts/vm/hypervisor/xenserver/ovs-get-dhcp-port.sh b/scripts/vm/hypervisor/xenserver/ovs-get-dhcp-port.sh old mode 100644 new mode 100755 diff --git a/scripts/vm/hypervisor/xenserver/ovs-pvlan b/scripts/vm/hypervisor/xenserver/ovs-pvlan index 372d3c8d05b..956ea6d7978 100755 --- a/scripts/vm/hypervisor/xenserver/ovs-pvlan +++ b/scripts/vm/hypervisor/xenserver/ovs-pvlan @@ -36,6 +36,7 @@ dhcpSetupPath = "/opt/xensource/bin/ovs-pvlan-dhcp-host.sh" vmSetupPath = "/opt/xensource/bin/ovs-pvlan-vm.sh" getDhcpPortPath = "/opt/xensource/bin/ovs-get-dhcp-port.sh" pvlanCleanupPath = "/opt/xensource/bin/ovs-pvlan-cleanup.sh" +getBridgePath = "/opt/xensource/bin/ovs-get-bridge.sh" def echo(fn): def wrapped(*v, **k): @@ -46,11 +47,10 @@ def echo(fn): return res return wrapped - @echo def setup_pvlan_dhcp(session, args): op = args.pop("op") - bridge = args.pop("bridge") + nw_label = args.pop("nw-label") primary = args.pop("primary-pvlan") isolated = args.pop("isolated-pvlan") dhcp_name = args.pop("dhcp-name") @@ -61,6 +61,10 @@ def setup_pvlan_dhcp(session, args): if res != "SUCCESS": return "FAILURE:%s" % res + logging.debug("Network is:%s" % (nw_label)) + bridge = lib.do_cmd([getBridgePath, nw_label]) + logging.debug("Determine bridge/switch is :%s" % (bridge)) + if op == "add": logging.debug("Try to get dhcp vm %s port on the switch:%s" % (dhcp_name, bridge)) dhcp_port = lib.do_cmd([getDhcpPortPath, bridge, dhcp_name]) @@ -88,7 +92,7 @@ def setup_pvlan_dhcp(session, args): @echo def setup_pvlan_vm(session, args): op = args.pop("op") - bridge = args.pop("bridge") + nw_label = args.pop("nw-label") primary = args.pop("primary-pvlan") isolated = args.pop("isolated-pvlan") vm_mac = args.pop("vm-mac") @@ -98,6 +102,9 @@ def setup_pvlan_vm(session, args): if res != "SUCCESS": return "FAILURE:%s" % res + bridge = lib.do_cmd([getBridgePath, nw_label]) + logging.debug("Determine bridge/switch is :%s" % (bridge)) + if op == "add": logging.debug("About to setup vm on the switch:%s" % bridge) res = lib.do_cmd([vmSetupPath, "-A", "-b", bridge, "-p", primary, "-i", isolated, "-v", vm_mac]) diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch index 97595190904..fe36ba9cb84 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver60/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch @@ -72,3 +72,4 @@ ovs-pvlan-dhcp-host.sh=../../../network,0755,/opt/xensource/bin ovs-pvlan-vm.sh=../../../network,0755,/opt/xensource/bin ovs-pvlan-cleanup.sh=../../../network,0755,/opt/xensource/bin ovs-get-dhcp-port.sh=..,0755,/opt/xensource/bin +ovs-get-bridge.sh=..,0755,/opt/xensource/bin diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 59a9f057162..a5098aeabd8 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -2219,7 +2219,9 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V if (!add) { op = "delete"; } - PvlanSetupCommand cmd = PvlanSetupCommand.createDhcpSetup(op, nic.getBroadcastUri(), router.getInstanceName(), nic.getMacAddress(), nic.getIp4Address()); + Network network = _networkDao.findById(nic.getNetworkId()); + String networkTag = _networkModel.getNetworkTag(router.getHypervisorType(), network); + PvlanSetupCommand cmd = PvlanSetupCommand.createDhcpSetup(op, nic.getBroadcastUri(), networkTag, router.getInstanceName(), nic.getMacAddress(), nic.getIp4Address()); Commands cmds = new Commands(cmd); // In fact we send command to the host of router, we're not programming router but the host try { diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 6ea295259a9..683f0daa1ee 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2761,7 +2761,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use // "delete" would remove all the rules(if using ovs) related to this vm op = "delete"; } - PvlanSetupCommand cmd = PvlanSetupCommand.createVmSetup(op, nic.getBroadcastUri(), nic.getMacAddress()); + Network network = _networkDao.findById(nic.getNetworkId()); + Host host = _hostDao.findById(hostId); + String networkTag = _networkModel.getNetworkTag(host.getHypervisorType(), network); + PvlanSetupCommand cmd = PvlanSetupCommand.createVmSetup(op, nic.getBroadcastUri(), networkTag, nic.getMacAddress()); Answer answer = null; try { answer = _agentMgr.send(hostId, cmd); From 3c3d67769b9b82c04ed670754fda8e36b7afc66a Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Wed, 1 May 2013 13:23:09 -0700 Subject: [PATCH 06/36] PVLAN: PvlanSetupCommand for KVM support --- .../resource/LibvirtComputingResource.java | 76 +++++++++++++++++++ .../hypervisor/kvm/resource/OvsVifDriver.java | 2 +- ...get-dhcp-port.sh => ovs-get-dhcp-iface.sh} | 3 +- scripts/vm/hypervisor/xenserver/ovs-pvlan | 6 +- .../vm/hypervisor/xenserver/xenserver60/patch | 2 +- scripts/vm/network/ovs-pvlan-dhcp-host.sh | 15 ++-- 6 files changed, 89 insertions(+), 15 deletions(-) rename scripts/vm/hypervisor/xenserver/{ovs-get-dhcp-port.sh => ovs-get-dhcp-iface.sh} (92%) diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 0064edf6a68..dc8bf9d86f7 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -125,6 +125,7 @@ import com.cloud.agent.api.PlugNicAnswer; import com.cloud.agent.api.PlugNicCommand; import com.cloud.agent.api.PrepareForMigrationAnswer; import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.PvlanSetupCommand; import com.cloud.agent.api.ReadyAnswer; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootAnswer; @@ -267,6 +268,8 @@ ServerResource { private String _createTmplPath; private String _heartBeatPath; private String _securityGroupPath; + private String _ovsPvlanDhcpHostPath; + private String _ovsPvlanVmPath; private String _routerProxyPath; private String _host; private String _dcId; @@ -587,6 +590,18 @@ ServerResource { "Unable to find the router_proxy.sh"); } + _ovsPvlanDhcpHostPath = Script.findScript(networkScriptsDir, "ovs-pvlan-dhcp-host.sh"); + if ( _ovsPvlanDhcpHostPath == null) { + throw new ConfigurationException( + "Unable to find the ovs-pvlan-dhcp-host.sh"); + } + + _ovsPvlanVmPath = Script.findScript(networkScriptsDir, "ovs-pvlan-vm.sh"); + if ( _ovsPvlanVmPath == null) { + throw new ConfigurationException( + "Unable to find the ovs-pvlan-vm.sh"); + } + String value = (String) params.get("developer"); boolean isDeveloper = Boolean.parseBoolean(value); @@ -1202,6 +1217,8 @@ ServerResource { return execute((CheckNetworkCommand) cmd); } else if (cmd instanceof NetworkRulesVmSecondaryIpCommand) { return execute((NetworkRulesVmSecondaryIpCommand) cmd); + } else if (cmd instanceof PvlanSetupCommand) { + return execute((PvlanSetupCommand) cmd); } else { s_logger.warn("Unsupported command "); return Answer.createUnsupportedCommandAnswer(cmd); @@ -1517,6 +1534,65 @@ ServerResource { } } + private Answer execute(PvlanSetupCommand cmd) { + String primaryPvlan = cmd.getPrimary(); + String isolatedPvlan = cmd.getIsolated(); + String op = cmd.getOp(); + String dhcpName = cmd.getDhcpName(); + String dhcpMac = cmd.getDhcpMac(); + String dhcpIp = cmd.getDhcpIp(); + String vmMac = cmd.getVmMac(); + boolean add = true; + + String opr = "-A"; + if (op.equals("delete")) { + opr = "-D"; + add = false; + } + + String result = null; + Connect conn; + try { + if (cmd.getType() == PvlanSetupCommand.Type.DHCP) { + Script script = new Script(_ovsPvlanDhcpHostPath, _timeout, s_logger); + if (add) { + conn = LibvirtConnection.getConnectionByVmName(dhcpName); + List ifaces = getInterfaces(conn, dhcpName); + InterfaceDef guestNic = ifaces.get(0); + script.add(opr, "-b", _guestBridgeName, + "-p", primaryPvlan, "-i", isolatedPvlan, "-n", dhcpName, + "-d", dhcpIp, "-m", dhcpMac, "-I", guestNic.getDevName()); + } else { + script.add(opr, "-b", _guestBridgeName, + "-p", primaryPvlan, "-i", isolatedPvlan, "-n", dhcpName, + "-d", dhcpIp, "-m", dhcpMac); + } + result = script.execute(); + if (result != null) { + s_logger.warn("Failed to program pvlan for dhcp server with mac " + dhcpMac); + return new Answer(cmd, false, result); + } else { + s_logger.info("Programmed pvlan for dhcp server with mac " + dhcpMac); + } + } else if (cmd.getType() == PvlanSetupCommand.Type.VM) { + Script script = new Script(_ovsPvlanVmPath, _timeout, s_logger); + script.add(opr, "-b", _guestBridgeName, + "-p", primaryPvlan, "-i", isolatedPvlan, "-v", vmMac); + result = script.execute(); + if (result != null) { + s_logger.warn("Failed to program pvlan for vm with mac " + vmMac); + return new Answer(cmd, false, result); + } else { + s_logger.info("Programmed pvlan for vm with mac " + vmMac); + } + } + } catch (LibvirtException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return new Answer(cmd, true, result); + } + private void VifHotPlug(Connect conn, String vmName, String vlanId, String macAddr) throws InternalErrorException, LibvirtException { NicTO nicTO = new NicTO(); diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java index 37761aa5555..ac226e212e5 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java @@ -79,7 +79,7 @@ public class OvsVifDriver extends VifDriverBase { } String trafficLabel = nic.getName(); if (nic.getType() == Networks.TrafficType.Guest) { - if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan + if ((nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan || nic.getBroadcastType() == Networks.BroadcastDomainType.Pvlan) && !vlanId.equalsIgnoreCase("untagged")) { if(trafficLabel != null && !trafficLabel.isEmpty()) { s_logger.debug("creating a vlan dev and bridge for guest traffic per traffic label " + trafficLabel); diff --git a/scripts/vm/hypervisor/xenserver/ovs-get-dhcp-port.sh b/scripts/vm/hypervisor/xenserver/ovs-get-dhcp-iface.sh similarity index 92% rename from scripts/vm/hypervisor/xenserver/ovs-get-dhcp-port.sh rename to scripts/vm/hypervisor/xenserver/ovs-get-dhcp-iface.sh index a30b180bed0..6b30ee62a06 100755 --- a/scripts/vm/hypervisor/xenserver/ovs-get-dhcp-port.sh +++ b/scripts/vm/hypervisor/xenserver/ovs-get-dhcp-iface.sh @@ -22,5 +22,4 @@ bridge=$1 dhcp_name=$2 dom_id=`xe vm-list is-control-domain=false power-state=running params=dom-id name-label=$dhcp_name|cut -d ':' -f 2 |tr -d ' ' ` iface="vif${dom_id}.0" -port=`ovs-ofctl show $bridge|grep $iface|cut -d '(' -f 1|tr -d ' '` -echo $port +echo $iface diff --git a/scripts/vm/hypervisor/xenserver/ovs-pvlan b/scripts/vm/hypervisor/xenserver/ovs-pvlan index 956ea6d7978..c821870d64d 100755 --- a/scripts/vm/hypervisor/xenserver/ovs-pvlan +++ b/scripts/vm/hypervisor/xenserver/ovs-pvlan @@ -34,7 +34,7 @@ xePath = "/opt/xensource/bin/xe" lib.setup_logging("/var/log/ovs-pvlan.log") dhcpSetupPath = "/opt/xensource/bin/ovs-pvlan-dhcp-host.sh" vmSetupPath = "/opt/xensource/bin/ovs-pvlan-vm.sh" -getDhcpPortPath = "/opt/xensource/bin/ovs-get-dhcp-port.sh" +getDhcpIfacePath = "/opt/xensource/bin/ovs-get-dhcp-iface.sh" pvlanCleanupPath = "/opt/xensource/bin/ovs-pvlan-cleanup.sh" getBridgePath = "/opt/xensource/bin/ovs-get-bridge.sh" @@ -67,11 +67,11 @@ def setup_pvlan_dhcp(session, args): if op == "add": logging.debug("Try to get dhcp vm %s port on the switch:%s" % (dhcp_name, bridge)) - dhcp_port = lib.do_cmd([getDhcpPortPath, bridge, dhcp_name]) + dhcp_iface = lib.do_cmd([getDhcpIfacePath, bridge, dhcp_name]) logging.debug("About to setup dhcp vm on the switch:%s" % bridge) res = lib.do_cmd([dhcpSetupPath, "-A", "-b", bridge, "-p", primary, "-i", isolated, "-n", dhcp_name, "-d", dhcp_ip, "-m", dhcp_mac, - "-P", dhcp_port]) + "-I", dhcp_iface]) if res: result = "FAILURE:%s" % res return result; diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch index fe36ba9cb84..9af32b1457a 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver60/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch @@ -71,5 +71,5 @@ ovs-pvlan=..,0755,/etc/xapi.d/plugins ovs-pvlan-dhcp-host.sh=../../../network,0755,/opt/xensource/bin ovs-pvlan-vm.sh=../../../network,0755,/opt/xensource/bin ovs-pvlan-cleanup.sh=../../../network,0755,/opt/xensource/bin -ovs-get-dhcp-port.sh=..,0755,/opt/xensource/bin +ovs-get-dhcp-iface.sh=..,0755,/opt/xensource/bin ovs-get-bridge.sh=..,0755,/opt/xensource/bin diff --git a/scripts/vm/network/ovs-pvlan-dhcp-host.sh b/scripts/vm/network/ovs-pvlan-dhcp-host.sh index 93f56534beb..73d735f822e 100755 --- a/scripts/vm/network/ovs-pvlan-dhcp-host.sh +++ b/scripts/vm/network/ovs-pvlan-dhcp-host.sh @@ -18,10 +18,8 @@ #!/bin/bash -source ovs-func.sh - usage() { - printf "Usage: %s: (-A|-D) -b -p -i -n -d -m -P -v -h \n" $(basename $0) >&2 + printf "Usage: %s: (-A|-D) -b -p -i -n -d -m -I -v -h \n" $(basename $0) >&2 exit 2 } @@ -31,11 +29,11 @@ sec_iso_vlan= dhcp_name= dhcp_ip= dhcp_mac= -dhcp_port= vm_mac= +iface= op= -while getopts 'ADb:p:i:d:m:v:n:P:h' OPTION +while getopts 'ADb:p:i:d:m:v:n:I:h' OPTION do case $OPTION in A) op="add" @@ -54,7 +52,7 @@ do ;; m) dhcp_mac="$OPTARG" ;; - P) dhcp_port="$OPTARG" + I) iface="$OPTARG" ;; v) vm_mac="$OPTARG" ;; @@ -106,14 +104,15 @@ then exit 1 fi -if [ "$op" == "add" -a -z "$dhcp_port" ] +if [ "$op" == "add" -a -z "$iface" ] then - echo Missing parameter DHCP PORT! + echo Missing parameter DHCP VM interface! exit 1 fi if [ "$op" == "add" ] then + dhcp_port=`ovs-ofctl show $br | grep $iface | cut -d '(' -f 1|tr -d ' '` ovs-ofctl add-flow $br priority=200,arp,dl_vlan=$sec_iso_vlan,nw_dst=$dhcp_ip,actions=strip_vlan,output:$dhcp_port ovs-ofctl add-flow $br priority=180,arp,nw_dst=$dhcp_ip,actions=strip_vlan,output:$dhcp_port ovs-ofctl add-flow $br priority=150,dl_vlan=$sec_iso_vlan,dl_dst=$dhcp_mac,actions=strip_vlan,output:$dhcp_port From 70da1b3be3b80d1bcc1ae652d9be81d26d3ef807 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Thu, 2 May 2013 16:32:07 -0700 Subject: [PATCH 07/36] PVLAN: Fix KVM ovs driver cannot get vlan id issue --- .../kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java index ac226e212e5..eac32485e53 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java @@ -76,6 +76,8 @@ public class OvsVifDriver extends VifDriverBase { } else if (nic.getBroadcastType() == Networks.BroadcastDomainType.Lswitch) { logicalSwitchUuid = nic.getBroadcastUri().getSchemeSpecificPart(); + } else if (nic.getBroadcastType() == Networks.BroadcastDomainType.Pvlan) { + vlanId = NetUtils.getPrimaryPvlanFromUri(nic.getBroadcastUri()); } String trafficLabel = nic.getName(); if (nic.getType() == Networks.TrafficType.Guest) { From 87b7a8450742b28183bc3e3245ba791959ce4e98 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Mon, 6 May 2013 12:14:19 -0700 Subject: [PATCH 08/36] CLOUDSTACK-2348: PVLAN - UI - infrastructure menu - create guest network - add new field Private VLAN ID. --- ui/scripts/system.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 7aa0566fbef..5eb88e0cf20 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -1375,7 +1375,10 @@ label: 'label.vlan.id', docID: 'helpGuestNetworkZoneVLANID' }, - + isolatedpvlanId: { + label: 'Private VLAN ID' + }, + scope: { label: 'label.scope', docID: 'helpGuestNetworkZoneScope', @@ -1589,11 +1592,15 @@ if(this.id == selectedNetworkOfferingId) { if(this.specifyvlan == false) { $form.find('.form-item[rel=vlanId]').hide(); - cloudStack.dialog.createFormField.validation.required.remove($form.find('.form-item[rel=vlanId]')); //make vlanId optional + cloudStack.dialog.createFormField.validation.required.remove($form.find('.form-item[rel=vlanId]')); //make vlanId optional + + $form.find('.form-item[rel=isolatedpvlanId]').hide(); } else { $form.find('.form-item[rel=vlanId]').css('display', 'inline-block'); - cloudStack.dialog.createFormField.validation.required.add($form.find('.form-item[rel=vlanId]')); //make vlanId required + cloudStack.dialog.createFormField.validation.required.add($form.find('.form-item[rel=vlanId]')); //make vlanId required + + $form.find('.form-item[rel=isolatedpvlanId]').css('display', 'inline-block'); } return false; //break each loop } @@ -1679,7 +1686,10 @@ if(($form.find('.form-item[rel=vlanId]').css("display") != "none") && (args.data.vlanId != null && args.data.vlanId.length > 0)) array1.push("&vlan=" + todb(args.data.vlanId)); - + + if(($form.find('.form-item[rel=isolatedpvlanId]').css("display") != "none") && (args.data.isolatedpvlanId != null && args.data.isolatedpvlanId.length > 0)) + array1.push("&isolatedpvlan=" + todb(args.data.isolatedpvlanId)); + if($form.find('.form-item[rel=domainId]').css("display") != "none") { array1.push("&domainId=" + args.data.domainId); From 0c7bd0777b9a5a5ec326b0d15fb0b3ef584235ab Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Mon, 6 May 2013 17:51:33 -0700 Subject: [PATCH 09/36] PVLAN: Optimize pvlan scripts --- scripts/vm/network/ovs-pvlan-dhcp-host.sh | 2 -- scripts/vm/network/ovs-pvlan-vm.sh | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/vm/network/ovs-pvlan-dhcp-host.sh b/scripts/vm/network/ovs-pvlan-dhcp-host.sh index 73d735f822e..64565ff45d1 100755 --- a/scripts/vm/network/ovs-pvlan-dhcp-host.sh +++ b/scripts/vm/network/ovs-pvlan-dhcp-host.sh @@ -114,12 +114,10 @@ if [ "$op" == "add" ] then dhcp_port=`ovs-ofctl show $br | grep $iface | cut -d '(' -f 1|tr -d ' '` ovs-ofctl add-flow $br priority=200,arp,dl_vlan=$sec_iso_vlan,nw_dst=$dhcp_ip,actions=strip_vlan,output:$dhcp_port - ovs-ofctl add-flow $br priority=180,arp,nw_dst=$dhcp_ip,actions=strip_vlan,output:$dhcp_port ovs-ofctl add-flow $br priority=150,dl_vlan=$sec_iso_vlan,dl_dst=$dhcp_mac,actions=strip_vlan,output:$dhcp_port ovs-ofctl add-flow $br priority=100,udp,dl_vlan=$sec_iso_vlan,nw_dst=255.255.255.255,tp_dst=67,actions=strip_vlan,output:$dhcp_port else ovs-ofctl del-flows --strict $br priority=200,arp,dl_vlan=$sec_iso_vlan,nw_dst=$dhcp_ip - ovs-ofctl del-flows --strict $br priority=180,arp,nw_dst=$dhcp_ip ovs-ofctl del-flows --strict $br priority=150,dl_vlan=$sec_iso_vlan,dl_dst=$dhcp_mac ovs-ofctl del-flows --strict $br priority=100,udp,dl_vlan=$sec_iso_vlan,nw_dst=255.255.255.255,tp_dst=67 fi diff --git a/scripts/vm/network/ovs-pvlan-vm.sh b/scripts/vm/network/ovs-pvlan-vm.sh index 4bad11c7624..fd384814cc4 100755 --- a/scripts/vm/network/ovs-pvlan-vm.sh +++ b/scripts/vm/network/ovs-pvlan-vm.sh @@ -91,7 +91,7 @@ trunk_port=1 if [ "$op" == "add" ] then ovs-ofctl add-flow $br priority=50,dl_vlan=0xffff,dl_src=$vm_mac,actions=mod_vlan_vid:$sec_iso_vlan,resubmit:$trunk_port - ovs-ofctl add-flow $br priority=60,dl_vlan=$sec_iso_vlan,dl_src=$vm_mac,actions=output:1 + ovs-ofctl add-flow $br priority=60,dl_vlan=$sec_iso_vlan,dl_src=$vm_mac,actions=output:$trunk_port else ovs-ofctl del-flows --strict $br priority=50,dl_vlan=0xffff,dl_src=$vm_mac ovs-ofctl del-flows --strict $br priority=60,dl_vlan=$sec_iso_vlan,dl_src=$vm_mac From 25e992dc8e1f2c202fba9c845d5913e2308ded90 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 7 May 2013 13:02:41 -0700 Subject: [PATCH 10/36] CLOUDSTACK-2348: PVLAN - UI - Infrastructure menu - guest network - add broadcast URI field to listView and detailView. --- ui/scripts/system.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 5eb88e0cf20..022f29995f3 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -1340,6 +1340,7 @@ name: { label: 'label.name' }, type: { label: 'label.type' }, vlan: { label: 'label.vlan.id' }, + broadcasturi: { label: 'broadcast URI' }, cidr: { label: 'IPv4 CIDR' }, ip6cidr: { label: 'IPv6 CIDR'} //scope: { label: 'label.scope' } @@ -2057,6 +2058,7 @@ } }, vlan: { label: 'label.vlan.id' }, + broadcasturi: { label: 'broadcast URI' }, scope: { label: 'label.scope' }, networkofferingdisplaytext: { label: 'label.network.offering' }, networkofferingid: { From 065d2561b9532c6f7536d22ce067d6085238a76b Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Mon, 13 May 2013 11:40:40 -0700 Subject: [PATCH 11/36] CLOUDSTACK-2392: Not allow create pvlan network with ipv6 --- server/src/com/cloud/network/NetworkServiceImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 7c4d7027c6b..ebada5c3fc3 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -1019,6 +1019,10 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { throw new InvalidParameterValueException("Can only support create Private VLAN network with advance shared network!"); } + if (isolatedPvlan != null && ipv6) { + throw new InvalidParameterValueException("Can only support create Private VLAN network with IPv4!"); + } + // Regular user can create Guest Isolated Source Nat enabled network only if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL && (ntwkOff.getTrafficType() != TrafficType.Guest || ntwkOff.getGuestType() != Network.GuestType.Isolated From 2bcf71638dba9a252378c251bbd32e6f72f74028 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Thu, 9 May 2013 19:44:14 -0700 Subject: [PATCH 12/36] PVLAN: Add integration test --- test/integration/smoke/test_pvlan.py | 86 ++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 test/integration/smoke/test_pvlan.py diff --git a/test/integration/smoke/test_pvlan.py b/test/integration/smoke/test_pvlan.py new file mode 100644 index 00000000000..4eb76e1cdb7 --- /dev/null +++ b/test/integration/smoke/test_pvlan.py @@ -0,0 +1,86 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +""" test for private vlan isolation +""" +#Import Local Modules +import marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin import remoteSSHClient +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from nose.plugins.attrib import attr +import telnetlib + +#Import System modules +import time +_multiprocess_shared_ = True + +class TestPVLAN(cloudstackTestCase): + + zoneId = 1 + networkOfferingId = 7 + vlan = 1234 + isolatedpvlan = 567 + + def setUp(self): + self.apiClient = self.testClient.getApiClient() + + def test_create_pvlan_network(self): + self.debug("Test create pvlan network") + createNetworkCmd = createNetwork.createNetworkCmd() + createNetworkCmd.name = "pvlan network" + createNetworkCmd.displaytext = "pvlan network" + createNetworkCmd.netmask = "255.255.255.0" + createNetworkCmd.gateway = "10.10.10.1" + createNetworkCmd.startip = "10.10.10.10" + createNetworkCmd.gateway = "10.10.10.20" + createNetworkCmd.vlan = "1234" + createNetworkCmd.isolatedpvlan = "567" + createNetworkCmd.zoneid = self.zoneId + createNetworkCmd.networkofferingid = self.networkOfferingId + createNetworkResponse = self.apiClient.createNetwork(createNetworkCmd) + self.networkId = createNetworkResponse.id + self.broadcasttype = createNetworkResponse.broadcastdomaintype + self.broadcasturi = createNetworkResponse.broadcasturi + + self.assertIsNotNone(createNetworkResponse.id, "Network failed to create") + self.assertTrue(createNetworkResponse.broadcastdomaintype, "Pvlan") + self.assertTrue(createNetworkResponse.broadcasturi, "pvlan://1234-i567") + + self.debug("Clean up test pvlan network") + deleteNetworkCmd = deleteNetwork.deleteNetworkCmd() + deleteNetworkCmd.id = self.networkId; + self.apiClient.deleteNetwork(deleteNetworkCmd) + + #Test invalid parameter + + # CLOUDSTACK-2392: Should not allow create pvlan with ipv6 + createNetworkCmd.ip6gateway="fc00:1234::1" + createNetworkCmd.ip6cidr="fc00:1234::/64" + createNetworkCmd.startipv6="fc00:1234::10" + createNetworkCmd.endipv6="fc00:1234::20" + err = 0; + try: + createNetworkResponse = self.apiClient.createNetwork(createNetworkCmd) + except Exception as e: + err = 1; + self.debug("Try alloc with ipv6, got:%s" % e) + self.assertEqual(err, 1, "Shouldn't allow create PVLAN network with IPv6"); + + From dbb223e4de54bdff4b805407d6d2ce3ea043f170 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Wed, 15 May 2013 10:32:32 -0700 Subject: [PATCH 13/36] Fixed applyLbRules for Netscaler. --- .../src/com/cloud/network/element/NetscalerElement.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java index 60d6674fdb4..cc2bcc17a43 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java @@ -240,7 +240,7 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl return false; } - if (canHandleLbRules(rules)) { + if (!canHandleLbRules(rules)) { return false; } From 7e0006a3e5584e0f89873ebfddf77c0bbcd4c222 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Wed, 15 May 2013 11:01:43 -0700 Subject: [PATCH 14/36] CLOUDSTACK-747: internalLb in VPC - UI - create tier dialog - only one tier is allowed to have PublicLb in a VPC. --- ui/scripts/sharedFunctions.js | 34 +++++++++++----------------------- ui/scripts/vpc.js | 9 +++++---- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index a01840637e3..035299059c2 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -122,34 +122,22 @@ function createURL(apiName, options) { return urlString; } -/* -function fromdb(val) { - return sanitizeXSS(noNull(val)); -} -*/ - function todb(val) { return encodeURIComponent(val); } -/* -function noNull(val) { - if(val == null) - return ""; - else - return val; -} -*/ +//LB provider map +var lbProviderMap = { + "publicLb": { + "non-vpc": ["VirtualRouter", "Netscaler", "F5"], + "vpc": ["VpcVirtualRouter", "Netscaler"] + }, + "internalLb": { + "non-vpc": [], + "vpc": ["InternalLbVm"] + } +}; -/* -function sanitizeXSS(val) { // Prevent cross-site-script(XSS) attack - if(val == null || typeof(val) != "string") - return val; - val = val.replace(//g, ">"); //replace > whose unicode is \u003e - return unescape(val); -} -*/ // Role Functions function isAdmin() { diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 0c4a446485b..4890dcc6ee9 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -2344,15 +2344,16 @@ var items; if(networkSupportingLbExists == true) { items = $.grep(networkOfferings, function(networkOffering) { - var includingLbService = false; + var includingPublicLbService = false; $(networkOffering.service).each(function(){ var thisService = this; - if(thisService.name == "Lb") { - includingLbService = true; + //only one tier is allowed to have PublicLb provider in a VPC + if(thisService.name == "Lb" && lbProviderMap.publicLb.vpc.indexOf(thisService.provider[0].name) != -1) { + includingPublicLbService = true; return false; //break $.each() loop } }); - return !includingLbService; + return !includingPublicLbService; }); } else { From a13dd59d167e70b3991ea666b83bdd240aa5e786 Mon Sep 17 00:00:00 2001 From: Prachi Damle Date: Tue, 14 May 2013 14:43:15 -0700 Subject: [PATCH 15/36] CLOUDSTACK-2486: Deleting the host_details and inserting them back can lead to mysql deadlock - Instead of using separate delete and insert, we will use ON DUPLICATE KEY UPDATE to avoid the MySQL deadlock --- .../entity/api/db/dao/HostDetailsDaoImpl.java | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/dao/HostDetailsDaoImpl.java b/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/dao/HostDetailsDaoImpl.java index 02f8c2c546c..e0ae778911c 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/dao/HostDetailsDaoImpl.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/dao/HostDetailsDaoImpl.java @@ -16,6 +16,8 @@ // under the License. package org.apache.cloudstack.engine.datacenter.entity.api.db.dao; +import java.sql.PreparedStatement; +import java.sql.SQLException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -30,18 +32,19 @@ import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; @Component(value="EngineHostDetailsDao") @Local(value=HostDetailsDao.class) public class HostDetailsDaoImpl extends GenericDaoBase implements HostDetailsDao { protected final SearchBuilder HostSearch; protected final SearchBuilder DetailSearch; - + public HostDetailsDaoImpl() { HostSearch = createSearchBuilder(); HostSearch.and("hostId", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ); HostSearch.done(); - + DetailSearch = createSearchBuilder(); DetailSearch.and("hostId", DetailSearch.entity().getHostId(), SearchCriteria.Op.EQ); DetailSearch.and("name", DetailSearch.entity().getName(), SearchCriteria.Op.EQ); @@ -53,7 +56,7 @@ public class HostDetailsDaoImpl extends GenericDaoBase implement SearchCriteria sc = DetailSearch.create(); sc.setParameters("hostId", hostId); sc.setParameters("name", name); - + DetailVO detail = findOneIncludingRemovedBy(sc); if("password".equals(name) && detail != null){ detail.setValue(DBEncryptionUtil.decrypt(detail.getValue())); @@ -65,7 +68,7 @@ public class HostDetailsDaoImpl extends GenericDaoBase implement public Map findDetails(long hostId) { SearchCriteria sc = HostSearch.create(); sc.setParameters("hostId", hostId); - + List results = search(sc, null); Map details = new HashMap(results.size()); for (DetailVO result : results) { @@ -77,12 +80,12 @@ public class HostDetailsDaoImpl extends GenericDaoBase implement } return details; } - + @Override public void deleteDetails(long hostId) { SearchCriteria sc = HostSearch.create(); sc.setParameters("hostId", hostId); - + List results = search(sc, null); for (DetailVO result : results) { remove(result.getId()); @@ -91,19 +94,27 @@ public class HostDetailsDaoImpl extends GenericDaoBase implement @Override public void persist(long hostId, Map details) { + final String InsertOrUpdateSql = "INSERT INTO `cloud`.`host_details` (host_id, name, value) VALUES (?,?,?) ON DUPLICATE KEY UPDATE value=?"; + Transaction txn = Transaction.currentTxn(); txn.start(); - SearchCriteria sc = HostSearch.create(); - sc.setParameters("hostId", hostId); - expunge(sc); - + for (Map.Entry detail : details.entrySet()) { - String value = detail.getValue(); - if("password".equals(detail.getKey())){ - value = DBEncryptionUtil.encrypt(value); - } - DetailVO vo = new DetailVO(hostId, detail.getKey(), value); - persist(vo); + String value = detail.getValue(); + if ("password".equals(detail.getKey())) { + value = DBEncryptionUtil.encrypt(value); + } + try { + PreparedStatement pstmt = txn.prepareAutoCloseStatement(InsertOrUpdateSql); + pstmt.setLong(1, hostId); + pstmt.setString(2, detail.getKey()); + pstmt.setString(3, value); + pstmt.setString(4, value); + pstmt.executeUpdate(); + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to persist the host_details key: " + detail.getKey() + + " for host id: " + hostId, e); + } } txn.commit(); } From d31217f3be2786951363e0859ef62d3c0b8c3643 Mon Sep 17 00:00:00 2001 From: Prachi Damle Date: Tue, 14 May 2013 17:29:13 -0700 Subject: [PATCH 16/36] CLOUDSTACK-2486: Deleting the host_details and inserting them back can lead to mysql deadlock - Added the index found missing after upgrade Contained in branches: master Contained in no tag --- .../cloud/upgrade/dao/Upgrade410to420.java | 69 ++++++++++++++----- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java index 1bd9abe780e..ff5e0fb0f88 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -73,9 +73,10 @@ public class Upgrade410to420 implements DbUpgrade { upgradeDefaultVpcOffering(conn); upgradePhysicalNtwksWithInternalLbProvider(conn); updateNetworkACLs(conn); + addHostDetailsIndex(conn); } - - private void updateSystemVmTemplates(Connection conn) { + + private void updateSystemVmTemplates(Connection conn) { PreparedStatement sql = null; try { sql = conn.prepareStatement("update vm_template set image_data_store_id = 1 where type = 'SYSTEM' or type = 'BUILTIN'"); @@ -91,7 +92,7 @@ public class Upgrade410to420 implements DbUpgrade { } } } - + private void updatePrimaryStore(Connection conn) { PreparedStatement sql = null; PreparedStatement sql2 = null; @@ -100,7 +101,7 @@ public class Upgrade410to420 implements DbUpgrade { sql.setString(1, "ancient primary data store provider"); sql.setString(2, "HOST"); sql.executeUpdate(); - + sql2 = conn.prepareStatement("update storage_pool set storage_provider_name = ? , scope = ? where pool_type != 'Filesystem' and pool_type != 'LVM'"); sql2.setString(1, "ancient primary data store provider"); sql2.setString(2, "CLUSTER"); @@ -114,7 +115,7 @@ public class Upgrade410to420 implements DbUpgrade { } catch (SQLException e) { } } - + if (sql2 != null) { try { sql2.close(); @@ -242,7 +243,7 @@ public class Upgrade410to420 implements DbUpgrade { } } } - + private void createPlaceHolderNics(Connection conn) { PreparedStatement pstmt = null; ResultSet rs = null; @@ -263,7 +264,7 @@ public class Upgrade410to420 implements DbUpgrade { pstmt.setLong(4, networkId); pstmt.executeUpdate(); s_logger.debug("Created placeholder nic for the ipAddress " + ip); - + } } catch (SQLException e) { throw new CloudRuntimeException("Unable to create placeholder nics", e); @@ -279,8 +280,8 @@ public class Upgrade410to420 implements DbUpgrade { } } } - - + + private void updateRemoteAccessVpn(Connection conn) { PreparedStatement pstmt = null; ResultSet rs = null; @@ -560,8 +561,8 @@ public class Upgrade410to420 implements DbUpgrade { } } } - - + + private void upgradeDefaultVpcOffering(Connection conn) { PreparedStatement pstmt = null; @@ -579,7 +580,7 @@ public class Upgrade410to420 implements DbUpgrade { pstmt.setString(3, "InternalLbVm"); pstmt.executeUpdate(); } - + } catch (SQLException e) { throw new CloudRuntimeException("Unable update the default VPC offering with the internal lb service", e); } finally { @@ -594,9 +595,9 @@ public class Upgrade410to420 implements DbUpgrade { } } } - - - + + + private void upgradePhysicalNtwksWithInternalLbProvider(Connection conn) { PreparedStatement pstmt = null; @@ -615,7 +616,7 @@ public class Upgrade410to420 implements DbUpgrade { pstmt.setString(1, uuid); pstmt.setLong(2, pNtwkId); pstmt.executeUpdate(); - + //Add internal lb vm to the list of physical network elements PreparedStatement pstmt1 = conn.prepareStatement("SELECT id FROM `cloud`.`physical_network_service_providers`" + " WHERE physical_network_id=? AND provider_name='InternalLbVm'"); @@ -629,7 +630,7 @@ public class Upgrade410to420 implements DbUpgrade { pstmt1.executeUpdate(); } } - + } catch (SQLException e) { throw new CloudRuntimeException("Unable existing physical networks with internal lb provider", e); } finally { @@ -643,6 +644,38 @@ public class Upgrade410to420 implements DbUpgrade { } catch (SQLException e) { } } - + + } + + private void addHostDetailsIndex(Connection conn) { + s_logger.debug("Checking if host_details index exists, if not we will add it"); + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + pstmt = conn.prepareStatement("SHOW INDEX FROM `cloud`.`host_details` where KEY_NAME = 'fk_host_details__host_id'"); + rs = pstmt.executeQuery(); + if (rs.next()) { + s_logger.debug("Index already exists on host_details - not adding new one"); + } else { + // add the index + PreparedStatement pstmtUpdate = conn.prepareStatement("ALTER IGNORE TABLE `cloud`.`host_details` ADD INDEX `fk_host_details__host_id` (`host_id`)"); + pstmtUpdate.executeUpdate(); + s_logger.debug("Index did not exist on host_details - added new one"); + pstmtUpdate.close(); + } + } catch (SQLException e) { + throw new CloudRuntimeException("Failed to check/update the host_details index ", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } } } From 73030f43729f408acd8c6325541db2f184757e80 Mon Sep 17 00:00:00 2001 From: Prachi Damle Date: Wed, 15 May 2013 11:58:13 -0700 Subject: [PATCH 17/36] CLOUDSTACK-2486: Deleting the host_details and inserting them back can lead to mysql deadlock - Changing the correct details dao. Instead of using separate delete and insert, we will use ON DUPLICATE KEY UPDATE to avoid the MySQL deadlock --- .../cloud/host/dao/HostDetailsDaoImpl.java | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/engine/schema/src/com/cloud/host/dao/HostDetailsDaoImpl.java b/engine/schema/src/com/cloud/host/dao/HostDetailsDaoImpl.java index b6a9cef9ee9..47cdeb30633 100644 --- a/engine/schema/src/com/cloud/host/dao/HostDetailsDaoImpl.java +++ b/engine/schema/src/com/cloud/host/dao/HostDetailsDaoImpl.java @@ -16,6 +16,8 @@ // under the License. package com.cloud.host.dao; +import java.sql.PreparedStatement; +import java.sql.SQLException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -30,18 +32,19 @@ import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; @Component @Local(value=HostDetailsDao.class) public class HostDetailsDaoImpl extends GenericDaoBase implements HostDetailsDao { protected final SearchBuilder HostSearch; protected final SearchBuilder DetailSearch; - + public HostDetailsDaoImpl() { HostSearch = createSearchBuilder(); HostSearch.and("hostId", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ); HostSearch.done(); - + DetailSearch = createSearchBuilder(); DetailSearch.and("hostId", DetailSearch.entity().getHostId(), SearchCriteria.Op.EQ); DetailSearch.and("name", DetailSearch.entity().getName(), SearchCriteria.Op.EQ); @@ -53,7 +56,7 @@ public class HostDetailsDaoImpl extends GenericDaoBase implement SearchCriteria sc = DetailSearch.create(); sc.setParameters("hostId", hostId); sc.setParameters("name", name); - + DetailVO detail = findOneIncludingRemovedBy(sc); if("password".equals(name) && detail != null){ detail.setValue(DBEncryptionUtil.decrypt(detail.getValue())); @@ -65,7 +68,7 @@ public class HostDetailsDaoImpl extends GenericDaoBase implement public Map findDetails(long hostId) { SearchCriteria sc = HostSearch.create(); sc.setParameters("hostId", hostId); - + List results = search(sc, null); Map details = new HashMap(results.size()); for (DetailVO result : results) { @@ -77,12 +80,12 @@ public class HostDetailsDaoImpl extends GenericDaoBase implement } return details; } - + @Override public void deleteDetails(long hostId) { SearchCriteria sc = HostSearch.create(); sc.setParameters("hostId", hostId); - + List results = search(sc, null); for (DetailVO result : results) { remove(result.getId()); @@ -91,19 +94,27 @@ public class HostDetailsDaoImpl extends GenericDaoBase implement @Override public void persist(long hostId, Map details) { + final String InsertOrUpdateSql = "INSERT INTO `cloud`.`host_details` (host_id, name, value) VALUES (?,?,?) ON DUPLICATE KEY UPDATE value=?"; + Transaction txn = Transaction.currentTxn(); txn.start(); - SearchCriteria sc = HostSearch.create(); - sc.setParameters("hostId", hostId); - expunge(sc); - + for (Map.Entry detail : details.entrySet()) { - String value = detail.getValue(); - if("password".equals(detail.getKey())){ - value = DBEncryptionUtil.encrypt(value); - } - DetailVO vo = new DetailVO(hostId, detail.getKey(), value); - persist(vo); + String value = detail.getValue(); + if ("password".equals(detail.getKey())) { + value = DBEncryptionUtil.encrypt(value); + } + try { + PreparedStatement pstmt = txn.prepareAutoCloseStatement(InsertOrUpdateSql); + pstmt.setLong(1, hostId); + pstmt.setString(2, detail.getKey()); + pstmt.setString(3, value); + pstmt.setString(4, value); + pstmt.executeUpdate(); + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to persist the host_details key: " + detail.getKey() + + " for host id: " + hostId, e); + } } txn.commit(); } From 9f59c618e277f4b9ce7e3cdd4156012b1d538471 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Wed, 15 May 2013 12:08:34 -0700 Subject: [PATCH 18/36] CLOUDSTACK-2517: fixed private gateway creation. Following fixes went in: 1) Only PrivateNetworkGuru handles network creation for the private gateway. Exluded Guest Network Guru from this list (was mistakenly included as a part of merge for Nicira integration) 2) Pass vpc_id to createNetwork call when the network is created as a part of private gateway creation 3) Fixed VPC restart when there are multiple private gateways present (have to grab all the private gateways when creating nic profiles for the VPC router that is being re-created) 4) 41-42 db upgarde: set vpc_id for the private networks of the existing VPCs --- .../src/com/cloud/network/dao/NetworkDao.java | 2 ++ .../com/cloud/network/dao/NetworkDaoImpl.java | 13 +++++++++ .../cloud/upgrade/dao/Upgrade410to420.java | 27 ++++++++++++++++++- .../com/cloud/network/NetworkServiceImpl.java | 2 +- .../guru/ExternalGuestNetworkGuru.java | 2 +- ...VpcVirtualNetworkApplianceManagerImpl.java | 14 +++++----- .../src/com/cloud/network/vpc/VpcManager.java | 2 +- .../com/cloud/network/vpc/VpcManagerImpl.java | 11 ++++---- .../com/cloud/vpc/MockVpcManagerImpl.java | 2 +- .../com/cloud/vpc/dao/MockNetworkDaoImpl.java | 5 ++++ 10 files changed, 64 insertions(+), 16 deletions(-) diff --git a/engine/schema/src/com/cloud/network/dao/NetworkDao.java b/engine/schema/src/com/cloud/network/dao/NetworkDao.java index 43cabe751f6..d0a1a256efc 100644 --- a/engine/schema/src/com/cloud/network/dao/NetworkDao.java +++ b/engine/schema/src/com/cloud/network/dao/NetworkDao.java @@ -113,4 +113,6 @@ public interface NetworkDao extends GenericDao , StateDao listRedundantNetworks(); List listByAclId(long aclId); + + int getNonSystemNetworkCountByVpcId(long vpcId); } diff --git a/engine/schema/src/com/cloud/network/dao/NetworkDaoImpl.java b/engine/schema/src/com/cloud/network/dao/NetworkDaoImpl.java index 5b3b526b640..c55cf28273a 100644 --- a/engine/schema/src/com/cloud/network/dao/NetworkDaoImpl.java +++ b/engine/schema/src/com/cloud/network/dao/NetworkDaoImpl.java @@ -162,6 +162,9 @@ public class NetworkDaoImpl extends GenericDaoBase implements N CountBy.and("offeringId", CountBy.entity().getNetworkOfferingId(), Op.EQ); CountBy.and("vpcId", CountBy.entity().getVpcId(), Op.EQ); CountBy.and("removed", CountBy.entity().getRemoved(), Op.NULL); + SearchBuilder ntwkOffJoin = _ntwkOffDao.createSearchBuilder(); + ntwkOffJoin.and("isSystem", ntwkOffJoin.entity().isSystemOnly(), Op.EQ); + CountBy.join("offerings", ntwkOffJoin, CountBy.entity().getNetworkOfferingId(), ntwkOffJoin.entity().getId(), JoinBuilder.JoinType.INNER); CountBy.done(); PhysicalNetworkSearch = createSearchBuilder(); @@ -627,4 +630,14 @@ public class NetworkDaoImpl extends GenericDaoBase implements N return listBy(sc, null); } + + + @Override + public int getNonSystemNetworkCountByVpcId(long vpcId) { + SearchCriteria sc = CountBy.create(); + sc.setParameters("vpcId", vpcId); + sc.setJoinParameters("offerings", "isSystem", false); + List results = customSearch(sc, null); + return results.get(0); + } } diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java index ff5e0fb0f88..1d35c8981fa 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -74,6 +74,7 @@ public class Upgrade410to420 implements DbUpgrade { upgradePhysicalNtwksWithInternalLbProvider(conn); updateNetworkACLs(conn); addHostDetailsIndex(conn); + updateNetworksForPrivateGateways(conn); } private void updateSystemVmTemplates(Connection conn) { @@ -564,7 +565,6 @@ public class Upgrade410to420 implements DbUpgrade { private void upgradeDefaultVpcOffering(Connection conn) { - PreparedStatement pstmt = null; ResultSet rs = null; @@ -678,4 +678,29 @@ public class Upgrade410to420 implements DbUpgrade { } } } + + + private void updateNetworksForPrivateGateways(Connection conn) { + + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + //1) get all non removed gateways + pstmt = conn.prepareStatement("SELECT network_id, vpc_id FROM `cloud`.`vpc_gateways` WHERE type='Private' AND removed IS null"); + rs = pstmt.executeQuery(); + while (rs.next()) { + Long networkId = rs.getLong(1); + Long vpcId = rs.getLong(2); + //2) Update networks with vpc_id if its set to NULL + pstmt = conn.prepareStatement("UPDATE `cloud`.`networks` set vpc_id=? where id=? and vpc_id is NULL and removed is NULL"); + pstmt.setLong(1, vpcId); + pstmt.setLong(2, networkId); + pstmt.executeUpdate(); + + } + } catch (SQLException e) { + throw new CloudRuntimeException("Failed to update private networks with VPC id.", e); + } + } } diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 5f51a30d389..8b11819577e 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -3813,7 +3813,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (privateNetwork == null) { //create Guest network privateNetwork = _networkMgr.createGuestNetwork(ntwkOff.getId(), networkName, displayText, gateway, cidr, vlan, - null, owner, null, pNtwk, pNtwk.getDataCenterId(), ACLType.Account, null, null, null, null, true); + null, owner, null, pNtwk, pNtwk.getDataCenterId(), ACLType.Account, null, vpcId, null, null, true); s_logger.debug("Created private network " + privateNetwork); } else { diff --git a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java index fe9e01f558d..eb1b3dc4b24 100644 --- a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java @@ -83,7 +83,7 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru { if (networkType == NetworkType.Advanced && isMyTrafficType(offering.getTrafficType()) && offering.getGuestType() == Network.GuestType.Isolated - && isMyIsolationMethod(physicalNetwork)) { + && isMyIsolationMethod(physicalNetwork) && !offering.isSystemOnly()) { return true; } else { s_logger.trace("We only take care of Guest networks of type " diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 915e2d8afe9..70073741433 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -1236,12 +1236,14 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian //1) allocate nic for control and source nat public ip networks = super.createRouterNetworks(owner, isRedundant, plan, null, sourceNatIp); - //2) allocate nic for private gateway if needed - PrivateGateway privateGateway = _vpcMgr.getVpcPrivateGateway(vpcId); - if (privateGateway != null) { - NicProfile privateNic = createPrivateNicProfileForGateway(privateGateway); - Network privateNetwork = _networkModel.getNetwork(privateGateway.getNetworkId()); - networks.add(new Pair((NetworkVO) privateNetwork, privateNic)); + //2) allocate nic for private gateways if needed + List privateGateways = _vpcMgr.getVpcPrivateGateways(vpcId); + if (privateGateways != null && !privateGateways.isEmpty()) { + for (PrivateGateway privateGateway : privateGateways) { + NicProfile privateNic = createPrivateNicProfileForGateway(privateGateway); + Network privateNetwork = _networkModel.getNetwork(privateGateway.getNetworkId()); + networks.add(new Pair((NetworkVO) privateNetwork, privateNic)); + } } //3) allocate nic for guest gateway if needed diff --git a/server/src/com/cloud/network/vpc/VpcManager.java b/server/src/com/cloud/network/vpc/VpcManager.java index e8db8d3fd5c..f22e7e4bf83 100644 --- a/server/src/com/cloud/network/vpc/VpcManager.java +++ b/server/src/com/cloud/network/vpc/VpcManager.java @@ -166,5 +166,5 @@ public interface VpcManager extends VpcService{ */ void validateNtwkOffForNtwkInVpc(Long networkId, long newNtwkOffId, String newCidr, String newNetworkDomain, Vpc vpc, String gateway, Account networkOwner); - List getVpcPrivateGateways(long id); + List getVpcPrivateGateways(long vpcId); } diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index f01d81be392..2335416e9fc 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -711,8 +711,9 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis public boolean destroyVpc(Vpc vpc, Account caller, Long callerUserId) throws ConcurrentOperationException, ResourceUnavailableException { s_logger.debug("Destroying vpc " + vpc); - //don't allow to delete vpc if it's in use by existing networks - int networksCount = _ntwkDao.getNetworkCountByVpcId(vpc.getId()); + //don't allow to delete vpc if it's in use by existing non system networks (system networks are networks of a private gateway of the VPC, + //and they will get removed as a part of VPC cleanup + int networksCount = _ntwkDao.getNonSystemNetworkCountByVpcId(vpc.getId()); if (networksCount > 0) { throw new InvalidParameterValueException("Can't delete VPC " + vpc + " as its used by " + networksCount + " networks"); } @@ -1235,7 +1236,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis return false; } - //4) Delete private gateway + //4) Delete private gateways List gateways = getVpcPrivateGateways(vpcId); if (gateways != null) { for (PrivateGateway gateway: gateways) { @@ -1299,8 +1300,8 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis @Override - public List getVpcPrivateGateways(long id) { - List gateways = _vpcGatewayDao.listByVpcIdAndType(id, VpcGateway.Type.Private); + public List getVpcPrivateGateways(long vpcId) { + List gateways = _vpcGatewayDao.listByVpcIdAndType(vpcId, VpcGateway.Type.Private); if (gateways != null) { List pvtGateway = new ArrayList(); diff --git a/server/test/com/cloud/vpc/MockVpcManagerImpl.java b/server/test/com/cloud/vpc/MockVpcManagerImpl.java index 9812750e479..921321f52da 100644 --- a/server/test/com/cloud/vpc/MockVpcManagerImpl.java +++ b/server/test/com/cloud/vpc/MockVpcManagerImpl.java @@ -379,7 +379,7 @@ public class MockVpcManagerImpl extends ManagerBase implements VpcManager { } @Override - public List getVpcPrivateGateways(long id) { + public List getVpcPrivateGateways(long vpcId) { return null; } diff --git a/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java b/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java index 4747e702e65..ec1a0173aa8 100644 --- a/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java +++ b/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java @@ -367,4 +367,9 @@ public class MockNetworkDaoImpl extends GenericDaoBase implemen return null; } + + @Override + public int getNonSystemNetworkCountByVpcId(long vpcId) { + return 0; + } } From ddd7cfd71c45c708012d30a0b7858db9d74c90f4 Mon Sep 17 00:00:00 2001 From: Prachi Damle Date: Wed, 15 May 2013 12:19:33 -0700 Subject: [PATCH 19/36] CLOUDSTACK-2519: VMs on local storage incorrectly destroyed when removing another host using deleteHost API - For DeleteHost API: Search for Volumes in READY state on the local storage of the host to find VM's in 'Running' State - For PrepareForMaintenance API: Search for Volumes not in Destroy or Expunging state to check if the Local Storage on the host is being used. --- .../com/cloud/storage/StorageManagerImpl.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 1d4dcefad92..a67397ec460 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -423,6 +423,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C SearchCriteria.Op.EQ); volumeSB.and("removed", volumeSB.entity().getRemoved(), SearchCriteria.Op.NULL); + volumeSB.and("state", volumeSB.entity().getState(), SearchCriteria.Op.NIN); SearchBuilder activeVmSB = _vmInstanceDao .createSearchBuilder(); @@ -434,6 +435,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C SearchCriteria volumeSC = volumeSB.create(); volumeSC.setParameters("poolId", PrimaryDataStoreVO.getId()); + volumeSC.setParameters("state", Volume.State.Expunging, Volume.State.Destroy); volumeSC.setJoinParameters("activeVmSB", "state", State.Starting, State.Running, State.Stopping, State.Migrating); @@ -456,13 +458,13 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C VirtualMachineProfile profile = new VirtualMachineProfileImpl( vm); for (StoragePoolAllocator allocator : _storagePoolAllocators) { - + ExcludeList avoidList = new ExcludeList(); for(StoragePool pool : avoid){ avoidList.addPool(pool.getId()); } DataCenterDeployment plan = new DataCenterDeployment(dc.getId(), pod.getId(), clusterId, hostId, null, null); - + final List poolList = allocator.allocateToPool(dskCh, profile, plan, avoidList, 1); if (poolList != null && !poolList.isEmpty()) { return (StoragePool)this.dataStoreMgr.getDataStore(poolList.get(0).getId(), DataStoreRole.Primary); @@ -629,6 +631,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C SearchCriteria.Op.EQ); volumeSearch.and("poolId", volumeSearch.entity().getPoolId(), SearchCriteria.Op.EQ); + volumeSearch.and("state", volumeSearch.entity().getState(), SearchCriteria.Op.EQ); StoragePoolSearch.join("vmVolume", volumeSearch, volumeSearch.entity() .getInstanceId(), StoragePoolSearch.entity().getId(), JoinBuilder.JoinType.INNER); @@ -651,7 +654,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C return true; } - + @Override public String getStoragePoolTags(long poolId) { return _configMgr.listToCsvTags(_storagePoolDao @@ -680,7 +683,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C return true; } - + @DB @Override public DataStore createLocalStorage(Host host, StoragePoolInfo pInfo) throws ConnectionException { @@ -694,7 +697,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C StoragePoolVO pool = _storagePoolDao.findPoolByHostPath(host.getDataCenterId(), host.getPodId(), pInfo.getHost(), pInfo.getHostPath(), pInfo.getUuid()); if(pool == null && host.getHypervisorType() == HypervisorType.VMware) { // perform run-time upgrade. In versions prior to 2.2.12, there is a bug that we don't save local datastore info (host path is empty), this will cause us - // not able to distinguish multiple local datastores that may be available on the host, to support smooth migration, we + // not able to distinguish multiple local datastores that may be available on the host, to support smooth migration, we // need to perform runtime upgrade here if(pInfo.getHostPath().length() > 0) { pool = _storagePoolDao.findPoolByHostPath(host.getDataCenterId(), host.getPodId(), pInfo.getHost(), "", pInfo.getUuid()); @@ -714,13 +717,13 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C params.put("details", pInfo.getDetails()); params.put("uuid", pInfo.getUuid()); params.put("providerName", provider.getName()); - + store = lifeCycle.initialize(params); } else { store = (DataStore) dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary); } - + HostScope scope = new HostScope(host.getId()); lifeCycle.attachHost(store, scope, pInfo); } catch (Exception e) { @@ -990,7 +993,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } CapacityState capacityState = (allocationState == AllocationState.Disabled) ? CapacityState.Disabled : CapacityState.Enabled; - + capacity.setCapacityState(capacityState); _capacityDao.persist(capacity); } else { @@ -1130,7 +1133,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C }finally { scanLock.unlock(); } - } + } }finally { scanLock.releaseRef(); } @@ -1462,7 +1465,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C DataStore store = dataStoreMgr.getDataStore( primaryStorage.getId(), DataStoreRole.Primary); lifeCycle.cancelMaintain(store); - + return (PrimaryDataStoreInfo) dataStoreMgr.getDataStore( primaryStorage.getId(), DataStoreRole.Primary); } @@ -1610,7 +1613,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C DataStoreRole.Primary); } - + @Override @DB @@ -1618,6 +1621,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C SearchCriteria sc = StoragePoolSearch.create(); sc.setJoinParameters("vmVolume", "volumeType", Volume.Type.ROOT); sc.setJoinParameters("vmVolume", "poolId", storagePoolId); + sc.setJoinParameters("vmVolume", "state", Volume.State.Ready); return _vmInstanceDao.search(sc, null); } @@ -1691,7 +1695,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C return secHost; } - + @Override public HypervisorType getHypervisorTypeFromFormat(ImageFormat format) { From c8af438e64abea2c4138fab13c1d4d5ab669ada0 Mon Sep 17 00:00:00 2001 From: Prachi Damle Date: Wed, 15 May 2013 14:27:27 -0700 Subject: [PATCH 20/36] CLOUDSTACK-2522: While processing agents behind on ping, we may fail to process a host that is already in 'Down' state Changes: - Added a transition for DOWN -> DOWN state on PING TIMEOUT so that transition will set mgmt_server_id in the host table to null. --- api/src/com/cloud/host/Status.java | 1 + 1 file changed, 1 insertion(+) diff --git a/api/src/com/cloud/host/Status.java b/api/src/com/cloud/host/Status.java index 97b151dc723..dd49122c13b 100755 --- a/api/src/com/cloud/host/Status.java +++ b/api/src/com/cloud/host/Status.java @@ -147,6 +147,7 @@ public enum Status { s_fsm.addTransition(Status.Down, Event.Remove, Status.Removed); s_fsm.addTransition(Status.Down, Event.ManagementServerDown, Status.Down); s_fsm.addTransition(Status.Down, Event.AgentDisconnected, Status.Down); + s_fsm.addTransition(Status.Down, Event.PingTimeout, Status.Down); s_fsm.addTransition(Status.Alert, Event.AgentConnected, Status.Connecting); s_fsm.addTransition(Status.Alert, Event.Ping, Status.Up); s_fsm.addTransition(Status.Alert, Event.Remove, Status.Removed); From 076c32db9a1733146a542cb23eb0515176bd5d0b Mon Sep 17 00:00:00 2001 From: Chiradeep Vittal Date: Wed, 15 May 2013 15:00:19 -0700 Subject: [PATCH 21/36] CLOUDSTACK-2492: enable time sync on vmware if ntp is not installed --- .../systemvm/debian/config/etc/init.d/cloud-early-config | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/patches/systemvm/debian/config/etc/init.d/cloud-early-config b/patches/systemvm/debian/config/etc/init.d/cloud-early-config index a457f228653..893a2455bc4 100755 --- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config +++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config @@ -434,6 +434,12 @@ setup_common() { ping -n -c 3 $MGMT_GW & sleep 3 pkill ping + + fi + + local hyp=$(hypervisor) + if [ "$hyp" == "vmware" ]; then + ntpq -p &> /dev/null || vmware-toolbox-cmd timesync enable fi } From 521e156520a3ca9514478c6871cde23d3e8e91f0 Mon Sep 17 00:00:00 2001 From: Chiradeep Vittal Date: Wed, 15 May 2013 15:33:57 -0700 Subject: [PATCH 22/36] CLOUDSTACK-2521: auto download ISO if not present --- tools/appliance/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index c39d38a4e76..0216c067a45 100644 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -34,7 +34,7 @@ bundle # Clean and start building the appliance veewee vbox destroy $appliance -veewee vbox build $appliance --nogui +veewee vbox build $appliance --nogui --auto veewee vbox halt $appliance while [[ `vboxmanage list runningvms | grep $appliance | wc -l` -ne 0 ]]; From 5511eb241af775efa59d4fdeb597d2b335b50739 Mon Sep 17 00:00:00 2001 From: Koushik Das Date: Thu, 16 May 2013 09:20:41 +0530 Subject: [PATCH 23/36] CLOUDSTACK-2509: [Cisco VNMC]No way to block incoming traffic as ACL created with PF/Static Nat is Source is Any No longer creating firewall rule as part of PF/Static NAT rule creation. Now firewall rule needs to be configured separately. Also made some changes to exception handling. --- .../network/cisco/create-egress-acl-rule.xml | 10 +- ...te-generic-egress-acl-no-protocol-rule.xml | 10 +- .../cisco/create-generic-egress-acl-rule.xml | 10 +- .../network/cisco/CiscoVnmcConnection.java | 4 +- .../cisco/CiscoVnmcConnectionImpl.java | 12 +- .../network/resource/CiscoVnmcResource.java | 149 ++++++++---------- 6 files changed, 88 insertions(+), 107 deletions(-) diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-egress-acl-rule.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-egress-acl-rule.xml index 05c066d6d53..f283ffeb333 100755 --- a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-egress-acl-rule.xml +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-egress-acl-rule.xml @@ -80,7 +80,7 @@ under the License. @@ -93,7 +93,7 @@ under the License. name="" placement="begin" status="created" - value="%deststartip%"/> + value="%sourcestartip%"/> + value="%sourceendip%"/> @@ -161,8 +161,8 @@ under the License. descr=value actiontype="drop" or "permit" protocolvalue = "TCP" or "UDP" - deststartip="destination start ip" - destendip="destination end ip" + sourcestartip="source start ip" + sourceendip="source end ip" deststartport="start port at destination" destendport="end port at destination" --!> diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-egress-acl-no-protocol-rule.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-egress-acl-no-protocol-rule.xml index 17cfa54a34e..e6f4cfb63d1 100755 --- a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-egress-acl-no-protocol-rule.xml +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-egress-acl-no-protocol-rule.xml @@ -54,7 +54,7 @@ under the License. @@ -67,7 +67,7 @@ under the License. name="" placement="begin" status="created" - value="%deststartip%"/> + value="%sourcestartip%"/> + value="%sourceendip%"/> @@ -89,6 +89,6 @@ under the License. aclrulename="dummy" descr=value actiontype="drop" or "permit" - deststartip="destination start ip" - destendip="destination end ip" + sourcestartip="source start ip" + sourceendip="source end ip" --!> diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-egress-acl-rule.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-egress-acl-rule.xml index 436e3eae790..55edd1fa728 100755 --- a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-egress-acl-rule.xml +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-egress-acl-rule.xml @@ -80,7 +80,7 @@ under the License. @@ -93,7 +93,7 @@ under the License. name="" placement="begin" status="created" - value="%deststartip%"/> + value="%sourcestartip%"/> + value="%sourceendip%"/> @@ -116,6 +116,6 @@ under the License. descr=value actiontype="drop" or "permit" protocolvalue = "TCP" or "UDP" or "ICMP" - deststartip="destination start ip" - destendip="destination end ip" + sourcestartip="source start ip" + sourceendip="source end ip" --!> diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnection.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnection.java index fed6724418d..28e2535ca91 100644 --- a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnection.java +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnection.java @@ -150,13 +150,13 @@ public interface CiscoVnmcConnection { public boolean createTenantVDCEgressAclRule(String tenantName, String identifier, String policyIdentifier, - String protocol, String destStartIp, String destEndIp, + String protocol, String sourceStartIp, String sourceEndIp, String destStartPort, String destEndPort) throws ExecutionException; public boolean createTenantVDCEgressAclRule(String tenantName, String identifier, String policyIdentifier, - String protocol, String destStartIp, String destEndIp) + String protocol, String sourceStartIp, String sourceEndIp) throws ExecutionException; public boolean deleteTenantVDCAclRule(String tenantName, diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java index 0e57cae6ddc..a9e8cf633f9 100644 --- a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java @@ -729,7 +729,7 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { @Override public boolean createTenantVDCEgressAclRule(String tenantName, String identifier, String policyIdentifier, - String protocol, String destStartIp, String destEndIp, + String protocol, String sourceStartIp, String sourceEndIp, String destStartPort, String destEndPort) throws ExecutionException { String xml = VnmcXml.CREATE_EGRESS_ACL_RULE.getXml(); String service = VnmcXml.CREATE_EGRESS_ACL_RULE.getService(); @@ -740,8 +740,8 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { xml = replaceXmlValue(xml, "descr", "Egress ACL rule for Tenant VDC " + tenantName); xml = replaceXmlValue(xml, "actiontype", "permit"); xml = replaceXmlValue(xml, "protocolvalue", protocol); - xml = replaceXmlValue(xml, "deststartip", destStartIp); - xml = replaceXmlValue(xml, "destendip", destEndIp); + xml = replaceXmlValue(xml, "sourcestartip", sourceStartIp); + xml = replaceXmlValue(xml, "sourceendip", sourceEndIp); xml = replaceXmlValue(xml, "deststartport", destStartPort); xml = replaceXmlValue(xml, "destendport", destEndPort); @@ -759,7 +759,7 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { @Override public boolean createTenantVDCEgressAclRule(String tenantName, String identifier, String policyIdentifier, - String protocol, String destStartIp, String destEndIp) throws ExecutionException { + String protocol, String sourceStartIp, String sourceEndIp) throws ExecutionException { String xml = VnmcXml.CREATE_GENERIC_EGRESS_ACL_RULE.getXml(); String service = VnmcXml.CREATE_GENERIC_EGRESS_ACL_RULE.getService(); if (protocol.equalsIgnoreCase("all")) { // any protocol @@ -773,8 +773,8 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { xml = replaceXmlValue(xml, "aclrulename", getNameForAclRule(tenantName, identifier)); xml = replaceXmlValue(xml, "descr", "Egress ACL rule for Tenant VDC " + tenantName); xml = replaceXmlValue(xml, "actiontype", "permit"); - xml = replaceXmlValue(xml, "deststartip", destStartIp); - xml = replaceXmlValue(xml, "destendip", destEndIp); + xml = replaceXmlValue(xml, "sourcestartip", sourceStartIp); + xml = replaceXmlValue(xml, "sourceendip", sourceEndIp); List rules = listChildren(getDnForAclPolicy(tenantName, policyIdentifier)); int order = 100; diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java index 176fdc45062..29bbbe67a31 100644 --- a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java @@ -60,6 +60,7 @@ import com.cloud.utils.Pair; import com.cloud.utils.cisco.n1kv.vsm.NetconfHelper; import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.OperationType; import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.SwitchPortMode; +import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.ExecutionException; import com.cloud.utils.net.NetUtils; @@ -280,30 +281,30 @@ public class CiscoVnmcResource implements ServerResource { String policyIdentifier = cmd.getIpAddress().getPublicIp().replace('.', '-'); try { if (!_connection.createTenantVDCNatPolicySet(tenant)) { - throw new Exception("Failed to create NAT policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create NAT policy set in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCSourceNatPolicy(tenant, policyIdentifier)) { - throw new Exception("Failed to create source NAT policy in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create source NAT policy in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCSourceNatPolicyRef(tenant, policyIdentifier)) { - throw new Exception("Failed to associate source NAT policy with NAT policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate source NAT policy with NAT policy set in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCSourceNatIpPool(tenant, policyIdentifier, cmd.getIpAddress().getPublicIp())) { - throw new Exception("Failed to create source NAT ip pool in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create source NAT ip pool in VNMC for guest network with vlan " + vlanId); } String[] ipRange = getIpRangeFromCidr(cmd.getContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR)); if (!_connection.createTenantVDCSourceNatRule(tenant, policyIdentifier, ipRange[0], ipRange[1])) { - throw new Exception("Failed to create source NAT rule in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create source NAT rule in VNMC for guest network with vlan " + vlanId); } if (!_connection.associateNatPolicySet(tenant)) { - throw new Exception("Failed to associate source NAT policy set with edge security profile in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate source NAT policy set with edge security profile in VNMC for guest network with vlan " + vlanId); } - } catch (Throwable e) { + } catch (ExecutionException e) { String msg = "SetSourceNatCommand failed due to " + e.getMessage(); s_logger.error(msg, e); return new Answer(cmd, false, msg); @@ -337,29 +338,29 @@ public class CiscoVnmcResource implements ServerResource { try { if (!_connection.createTenantVDCAclPolicySet(tenant, true)) { - throw new Exception("Failed to create ACL ingress policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create ACL ingress policy set in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCAclPolicySet(tenant, false)) { - throw new Exception("Failed to create ACL egress policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create ACL egress policy set in VNMC for guest network with vlan " + vlanId); } for (String publicIp : publicIpRulesMap.keySet()) { String policyIdentifier = publicIp.replace('.', '-'); if (!_connection.createTenantVDCAclPolicy(tenant, policyIdentifier)) { - throw new Exception("Failed to create ACL policy in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create ACL policy in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, true)) { - throw new Exception("Failed to associate ACL policy with ACL ingress policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate ACL policy with ACL ingress policy set in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, false)) { - throw new Exception("Failed to associate ACL policy with ACL egress policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate ACL policy with ACL egress policy set in VNMC for guest network with vlan " + vlanId); } for (FirewallRuleTO rule : publicIpRulesMap.get(publicIp)) { if (rule.revoked()) { if (!_connection.deleteTenantVDCAclRule(tenant, Long.toString(rule.getId()), policyIdentifier)) { - throw new Exception("Failed to delete ACL rule in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to delete ACL rule in VNMC for guest network with vlan " + vlanId); } } else { String[] externalIpRange = getIpRangeFromCidr(rule.getSourceCidrList().get(0)); @@ -370,13 +371,13 @@ public class CiscoVnmcResource implements ServerResource { Long.toString(rule.getId()), policyIdentifier, rule.getProtocol().toUpperCase(), externalIpRange[0], externalIpRange[1], Integer.toString(rule.getSrcPortRange()[0]), Integer.toString(rule.getSrcPortRange()[1]))) { - throw new Exception("Failed to create ACL ingress rule in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create ACL ingress rule in VNMC for guest network with vlan " + vlanId); } } else { if (!_connection.createTenantVDCIngressAclRule(tenant, Long.toString(rule.getId()), policyIdentifier, rule.getProtocol().toUpperCase(), externalIpRange[0], externalIpRange[1])) { - throw new Exception("Failed to create ACL ingress rule in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create ACL ingress rule in VNMC for guest network with vlan " + vlanId); } } } else { @@ -387,13 +388,13 @@ public class CiscoVnmcResource implements ServerResource { rule.getProtocol().toUpperCase(), externalIpRange[0], externalIpRange[1], Integer.toString(rule.getSrcPortRange()[0]), Integer.toString(rule.getSrcPortRange()[1]))) { - throw new Exception("Failed to create ACL egress rule in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create ACL egress rule in VNMC for guest network with vlan " + vlanId); } } else { if (!_connection.createTenantVDCEgressAclRule(tenant, Long.toString(rule.getId()), policyIdentifier, rule.getProtocol().toUpperCase(), externalIpRange[0], externalIpRange[1])) { - throw new Exception("Failed to create ACL egress rule in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create ACL egress rule in VNMC for guest network with vlan " + vlanId); } } } @@ -402,9 +403,9 @@ public class CiscoVnmcResource implements ServerResource { } if (!_connection.associateAclPolicySet(tenant)) { - throw new Exception("Failed to associate ACL policy set with edge security profile in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate ACL policy set with edge security profile in VNMC for guest network with vlan " + vlanId); } - } catch (Throwable e) { + } catch (ExecutionException e) { String msg = "SetFirewallRulesCommand failed due to " + e.getMessage(); s_logger.error(msg, e); return new Answer(cmd, false, msg); @@ -438,69 +439,60 @@ public class CiscoVnmcResource implements ServerResource { try { if (!_connection.createTenantVDCNatPolicySet(tenant)) { - throw new Exception("Failed to create NAT policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create NAT policy set in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCAclPolicySet(tenant, true)) { - throw new Exception("Failed to create ACL ingress policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create ACL ingress policy set in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCAclPolicySet(tenant, false)) { - throw new Exception("Failed to create ACL egress policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create ACL egress policy set in VNMC for guest network with vlan " + vlanId); } for (String publicIp : publicIpRulesMap.keySet()) { String policyIdentifier = publicIp.replace('.', '-'); if (!_connection.createTenantVDCDNatPolicy(tenant, policyIdentifier)) { - throw new Exception("Failed to create DNAT policy in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create DNAT policy in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCDNatPolicyRef(tenant, policyIdentifier)) { - throw new Exception("Failed to associate DNAT policy with NAT policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate DNAT policy with NAT policy set in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCAclPolicy(tenant, policyIdentifier)) { - throw new Exception("Failed to create ACL policy in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create ACL policy in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, true)) { - throw new Exception("Failed to associate ACL policy with ACL ingress policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate ACL policy with ACL ingress policy set in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, false)) { - throw new Exception("Failed to associate ACL policy with ACL egress policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate ACL policy with ACL egress policy set in VNMC for guest network with vlan " + vlanId); } for (StaticNatRuleTO rule : publicIpRulesMap.get(publicIp)) { if (rule.revoked()) { if (!_connection.deleteTenantVDCDNatRule(tenant, Long.toString(rule.getId()), policyIdentifier)) { - throw new Exception("Failed to delete DNAT rule in VNMC for guest network with vlan " + vlanId); - } - - if (!_connection.deleteTenantVDCAclRule(tenant, Long.toString(rule.getId()), policyIdentifier)) { - throw new Exception("Failed to delete ACL ingress rule for DNAT in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to delete DNAT rule in VNMC for guest network with vlan " + vlanId); } } else { if (!_connection.createTenantVDCDNatIpPool(tenant, Long.toString(rule.getId()), rule.getDstIp())) { - throw new Exception("Failed to create DNAT ip pool in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create DNAT ip pool in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCDNatRule(tenant, Long.toString(rule.getId()), policyIdentifier, rule.getSrcIp())) { - throw new Exception("Failed to create DNAT rule in VNMC for guest network with vlan " + vlanId); - } - - if (!_connection.createTenantVDCAclRuleForDNat(tenant, - Long.toString(rule.getId()), policyIdentifier, rule.getDstIp())) { - throw new Exception("Failed to create ACL rule for DNAT in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create DNAT rule in VNMC for guest network with vlan " + vlanId); } } } } if (!_connection.associateAclPolicySet(tenant)) { - throw new Exception("Failed to associate source NAT policy set with edge security profile in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate source NAT policy set with edge security profile in VNMC for guest network with vlan " + vlanId); } - } catch (Throwable e) { - String msg = "SetSourceNatCommand failed due to " + e.getMessage(); + } catch (ExecutionException e) { + String msg = "SetStaticNatRulesCommand failed due to " + e.getMessage(); s_logger.error(msg, e); return new Answer(cmd, false, msg); } @@ -533,77 +525,66 @@ public class CiscoVnmcResource implements ServerResource { try { if (!_connection.createTenantVDCNatPolicySet(tenant)) { - throw new Exception("Failed to create NAT policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create NAT policy set in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCAclPolicySet(tenant, true)) { - throw new Exception("Failed to create ACL ingress policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create ACL ingress policy set in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCAclPolicySet(tenant, false)) { - throw new Exception("Failed to create ACL egress policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create ACL egress policy set in VNMC for guest network with vlan " + vlanId); } for (String publicIp : publicIpRulesMap.keySet()) { String policyIdentifier = publicIp.replace('.', '-'); if (!_connection.createTenantVDCPFPolicy(tenant, policyIdentifier)) { - throw new Exception("Failed to create PF policy in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create PF policy in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCPFPolicyRef(tenant, policyIdentifier)) { - throw new Exception("Failed to associate PF policy with NAT policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate PF policy with NAT policy set in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCAclPolicy(tenant, policyIdentifier)) { - throw new Exception("Failed to create ACL policy in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create ACL policy in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, true)) { - throw new Exception("Failed to associate ACL policy with ACL ingress policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate ACL policy with ACL ingress policy set in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, false)) { - throw new Exception("Failed to associate ACL policy with ACL egress policy set in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate ACL policy with ACL egress policy set in VNMC for guest network with vlan " + vlanId); } for (PortForwardingRuleTO rule : publicIpRulesMap.get(publicIp)) { if (rule.revoked()) { if (!_connection.deleteTenantVDCPFRule(tenant, Long.toString(rule.getId()), policyIdentifier)) { - throw new Exception("Failed to delete PF rule in VNMC for guest network with vlan " + vlanId); - } - - if (!_connection.deleteTenantVDCAclRule(tenant, Long.toString(rule.getId()), policyIdentifier)) { - throw new Exception("Failed to delete ACL ingress rule for PF in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to delete PF rule in VNMC for guest network with vlan " + vlanId); } } else { if (!_connection.createTenantVDCPFIpPool(tenant, Long.toString(rule.getId()), rule.getDstIp())) { - throw new Exception("Failed to create PF ip pool in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create PF ip pool in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCPFPortPool(tenant, Long.toString(rule.getId()), Integer.toString(rule.getDstPortRange()[0]), Integer.toString(rule.getDstPortRange()[1]))) { - throw new Exception("Failed to create PF port pool in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create PF port pool in VNMC for guest network with vlan " + vlanId); } if (!_connection.createTenantVDCPFRule(tenant, Long.toString(rule.getId()), policyIdentifier, rule.getProtocol().toUpperCase(), rule.getSrcIp(), Integer.toString(rule.getSrcPortRange()[0]), Integer.toString(rule.getSrcPortRange()[1]))) { - throw new Exception("Failed to create PF rule in VNMC for guest network with vlan " + vlanId); - } - - if (!_connection.createTenantVDCAclRuleForPF(tenant, - Long.toString(rule.getId()), policyIdentifier, - rule.getProtocol().toUpperCase(), rule.getDstIp(), - Integer.toString(rule.getDstPortRange()[0]), Integer.toString(rule.getDstPortRange()[1]))) { - throw new Exception("Failed to create ACL rule for PF in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create PF rule in VNMC for guest network with vlan " + vlanId); } } } } if (!_connection.associateAclPolicySet(tenant)) { - throw new Exception("Failed to associate source NAT policy set with edge security profile in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate source NAT policy set with edge security profile in VNMC for guest network with vlan " + vlanId); } - } catch (Throwable e) { - String msg = "SetSourceNatCommand failed due to " + e.getMessage(); + } catch (ExecutionException e) { + String msg = "SetPortForwardingRulesCommand failed due to " + e.getMessage(); s_logger.error(msg, e); return new Answer(cmd, false, msg); } @@ -619,24 +600,24 @@ public class CiscoVnmcResource implements ServerResource { return execute(cmd, _numRetries); } - private void createEdgeDeviceProfile(String tenant, List gateways, Long vlanId) throws Exception { + private void createEdgeDeviceProfile(String tenant, List gateways, Long vlanId) throws ExecutionException { // create edge device profile if (!_connection.createTenantVDCEdgeDeviceProfile(tenant)) - throw new Exception("Failed to create tenant edge device profile in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create tenant edge device profile in VNMC for guest network with vlan " + vlanId); // create edge static route policy if (!_connection.createTenantVDCEdgeStaticRoutePolicy(tenant)) - throw new Exception("Failed to create tenant edge static route policy in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create tenant edge static route policy in VNMC for guest network with vlan " + vlanId); // create edge static route for all gateways for (String gateway : gateways) { if (!_connection.createTenantVDCEdgeStaticRoute(tenant, gateway, "0.0.0.0", "0.0.0.0")) - throw new Exception("Failed to create tenant edge static route in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to create tenant edge static route in VNMC for guest network with vlan " + vlanId); } // associate edge if (!_connection.associateTenantVDCEdgeStaticRoutePolicy(tenant)) - throw new Exception("Failed to associate edge static route policy with edge device profile in VNMC for guest network with vlan " + vlanId); + throw new ExecutionException("Failed to associate edge static route policy with edge device profile in VNMC for guest network with vlan " + vlanId); } private Answer execute(CreateLogicalEdgeFirewallCommand cmd, int numRetries) { @@ -644,23 +625,23 @@ public class CiscoVnmcResource implements ServerResource { try { // create tenant if (!_connection.createTenant(tenant)) - throw new Exception("Failed to create tenant in VNMC for guest network with vlan " + cmd.getVlanId()); + throw new ExecutionException("Failed to create tenant in VNMC for guest network with vlan " + cmd.getVlanId()); // create tenant VDC if (!_connection.createTenantVDC(tenant)) - throw new Exception("Failed to create tenant VDC in VNMC for guest network with vlan " + cmd.getVlanId()); + throw new ExecutionException("Failed to create tenant VDC in VNMC for guest network with vlan " + cmd.getVlanId()); // create edge security profile if (!_connection.createTenantVDCEdgeSecurityProfile(tenant)) - throw new Exception("Failed to create tenant edge security profile in VNMC for guest network with vlan " + cmd.getVlanId()); + throw new ExecutionException("Failed to create tenant edge security profile in VNMC for guest network with vlan " + cmd.getVlanId()); // create edge device profile and associated route createEdgeDeviceProfile(tenant, cmd.getPublicGateways(), cmd.getVlanId()); // create logical edge firewall if (!_connection.createEdgeFirewall(tenant, cmd.getPublicIp(), cmd.getInternalIp(), cmd.getPublicSubnet(), cmd.getInternalSubnet())) - throw new Exception("Failed to create edge firewall in VNMC for guest network with vlan " + cmd.getVlanId()); - } catch (Throwable e) { + throw new ExecutionException("Failed to create edge firewall in VNMC for guest network with vlan " + cmd.getVlanId()); + } catch (ExecutionException e) { String msg = "CreateLogicalEdgeFirewallCommand failed due to " + e.getMessage(); s_logger.error(msg, e); return new Answer(cmd, false, msg); @@ -688,7 +669,7 @@ public class CiscoVnmcResource implements ServerResource { s_logger.debug("Created vservice node for ASA appliance in Cisco VSM for vlan " + vlanId); helper.updatePortProfile(cmd.getAsaInPortProfile(), SwitchPortMode.access, params); s_logger.debug("Updated inside port profile for ASA appliance in Cisco VSM with new vlan " + vlanId); - } catch (Throwable e) { + } catch (CloudRuntimeException e) { String msg = "ConfigureVSMForASACommand failed due to " + e.getMessage(); s_logger.error(msg, e); return new Answer(cmd, false, msg); @@ -711,18 +692,18 @@ public class CiscoVnmcResource implements ServerResource { try { Map availableAsaAppliances = _connection.listUnAssocAsa1000v(); if (availableAsaAppliances.isEmpty()) { - throw new Exception("No ASA 1000v available to associate with logical edge firewall for guest vlan " + cmd.getVlanId()); + throw new ExecutionException("No ASA 1000v available to associate with logical edge firewall for guest vlan " + cmd.getVlanId()); } String asaInstanceDn = availableAsaAppliances.get(cmd.getAsaMgmtIp()); if (asaInstanceDn == null) { - throw new Exception("Requested ASA 1000v (" + cmd.getAsaMgmtIp() + ") is not available"); + throw new ExecutionException("Requested ASA 1000v (" + cmd.getAsaMgmtIp() + ") is not available"); } if (!_connection.assignAsa1000v(tenant, asaInstanceDn)) { - throw new Exception("Failed to associate ASA 1000v (" + cmd.getAsaMgmtIp() + ") with logical edge firewall for guest vlan " + cmd.getVlanId()); + throw new ExecutionException("Failed to associate ASA 1000v (" + cmd.getAsaMgmtIp() + ") with logical edge firewall for guest vlan " + cmd.getVlanId()); } - } catch (Throwable e) { + } catch (ExecutionException e) { String msg = "AssociateAsaWithLogicalEdgeFirewallCommand failed due to " + e.getMessage(); s_logger.error(msg, e); return new Answer(cmd, false, msg); @@ -743,7 +724,7 @@ public class CiscoVnmcResource implements ServerResource { String tenant = "vlan-" + cmd.getVlanId(); try { _connection.deleteTenant(tenant); - } catch (Throwable e) { + } catch (ExecutionException e) { String msg = "CleanupLogicalEdgeFirewallCommand failed due to " + e.getMessage(); s_logger.error(msg, e); return new Answer(cmd, false, msg); From a37fa39fe75925716c2b9998d40d4e95e78bbcdd Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Wed, 15 May 2013 16:45:56 +0530 Subject: [PATCH 24/36] multiple fixes to regression tests - remove references to account.account - remove ostypeid references - correct zone.networktype - correct storage_motion assert. skip on invalid environmetn Signed-off-by: Prasanna Santhanam --- test/integration/component/test_accounts.py | 71 ++++---- .../component/test_resource_limits.py | 154 +++++++++--------- .../component/test_storage_motion.py | 6 + .../component/test_vm_passwdenabled.py | 2 +- 4 files changed, 119 insertions(+), 114 deletions(-) diff --git a/test/integration/component/test_accounts.py b/test/integration/component/test_accounts.py index 9cbefe55fdb..b2038a9bd3b 100644 --- a/test/integration/component/test_accounts.py +++ b/test/integration/component/test_accounts.py @@ -78,7 +78,6 @@ class Services: "template": { "displaytext": "Public Template", "name": "Public template", - "ostypeid": 'bc66ada0-99e7-483b-befc-8fb0c2129b70', "url": "http://download.cloud.com/releases/2.0.0/UbuntuServer-10-04-64bit.vhd.bz2", "hypervisor": 'XenServer', "format": 'VHD', @@ -243,7 +242,7 @@ class TestRemoveUserFromAccount(cloudstackTestCase): cls.template = get_template( cls.api_client, cls.zone.id, - cls.services["ostypeid"] + cls.services["ostype"] ) cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["virtual_machine"]["template"] = cls.template.id @@ -568,7 +567,7 @@ class TestNonRootAdminsPrivileges(cloudstackTestCase): self.apiclient, self.services["account"] ) - self.debug("Created account: %s" % account_2.account.name) + self.debug("Created account: %s" % account_2.name) self.cleanup.append(account_2) accounts_response = list_accounts( @@ -886,7 +885,7 @@ class TesttemplateHierarchy(cloudstackTestCase): cls.template = Template.register( cls.api_client, cls.services["template"], - account=cls.account_1.account.name, + account=cls.account_1.name, domainid=cls.domain_1.id ) cls._cleanup = [ @@ -935,7 +934,7 @@ class TesttemplateHierarchy(cloudstackTestCase): templates = list_templates( self.apiclient, templatefilter='self', - account=self.account_1.account.name, + account=self.account_1.name, domainid=self.domain_1.id ) self.assertEqual( @@ -960,7 +959,7 @@ class TesttemplateHierarchy(cloudstackTestCase): templates = list_templates( self.apiclient, templatefilter='self', - account=self.account_2.account.name, + account=self.account_2.name, domainid=self.domain_2.id ) self.assertEqual( @@ -1033,15 +1032,15 @@ class TestAddVmToSubDomain(cloudstackTestCase): cls.template = get_template( cls.api_client, cls.zone.id, - cls.services["ostypeid"] + cls.services["ostype"] ) cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.vm_1 = VirtualMachine.create( cls.api_client, cls.services["virtual_machine"], templateid=cls.template.id, - accountid=cls.account_1.account.name, - domainid=cls.account_1.account.domainid, + accountid=cls.account_1.name, + domainid=cls.account_1.domainid, serviceofferingid=cls.service_offering.id ) @@ -1049,8 +1048,8 @@ class TestAddVmToSubDomain(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], templateid=cls.template.id, - accountid=cls.account_2.account.name, - domainid=cls.account_2.account.domainid, + accountid=cls.account_2.name, + domainid=cls.account_2.domainid, serviceofferingid=cls.service_offering.id ) cls._cleanup = [ @@ -1625,7 +1624,7 @@ class TestDomainForceRemove(cloudstackTestCase): cls.template = get_template( cls.api_client, cls.zone.id, - cls.services["ostypeid"] + cls.services["ostype"] ) cls.services["virtual_machine"]["zoneid"] = cls.zone.id @@ -1719,31 +1718,31 @@ class TestDomainForceRemove(cloudstackTestCase): ) self.debug("Deploying virtual machine in account 1: %s" % - self.account_1.account.name) + self.account_1.name) vm_1 = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], templateid=self.template.id, - accountid=self.account_1.account.name, - domainid=self.account_1.account.domainid, + accountid=self.account_1.name, + domainid=self.account_1.domainid, serviceofferingid=self.service_offering.id ) self.debug("Deploying virtual machine in account 2: %s" % - self.account_2.account.name) + self.account_2.name) vm_2 = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], templateid=self.template.id, - accountid=self.account_2.account.name, - domainid=self.account_2.account.domainid, + accountid=self.account_2.name, + domainid=self.account_2.domainid, serviceofferingid=self.service_offering.id ) networks = Network.list( self.apiclient, - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, listall=True ) self.assertEqual( @@ -1753,13 +1752,13 @@ class TestDomainForceRemove(cloudstackTestCase): ) network_1 = networks[0] self.debug("Default network in account 1: %s is %s" % ( - self.account_1.account.name, + self.account_1.name, network_1.name)) src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=network_1.id, - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, listall=True, issourcenat=True, ) @@ -1823,8 +1822,8 @@ class TestDomainForceRemove(cloudstackTestCase): self.debug("Checking if the resources in domain are deleted or not..") accounts = Account.list( self.apiclient, - name=self.account_1.account.name, - domainid=self.account_1.account.domainid, + name=self.account_1.name, + domainid=self.account_1.domainid, listall=True ) @@ -1894,31 +1893,31 @@ class TestDomainForceRemove(cloudstackTestCase): self.cleanup.append(self.service_offering) self.debug("Deploying virtual machine in account 1: %s" % - self.account_1.account.name) + self.account_1.name) vm_1 = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], templateid=self.template.id, - accountid=self.account_1.account.name, - domainid=self.account_1.account.domainid, + accountid=self.account_1.name, + domainid=self.account_1.domainid, serviceofferingid=self.service_offering.id ) self.debug("Deploying virtual machine in account 2: %s" % - self.account_2.account.name) + self.account_2.name) vm_2 = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], templateid=self.template.id, - accountid=self.account_2.account.name, - domainid=self.account_2.account.domainid, + accountid=self.account_2.name, + domainid=self.account_2.domainid, serviceofferingid=self.service_offering.id ) networks = Network.list( self.apiclient, - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, listall=True ) self.assertEqual( @@ -1928,13 +1927,13 @@ class TestDomainForceRemove(cloudstackTestCase): ) network_1 = networks[0] self.debug("Default network in account 1: %s is %s" % ( - self.account_1.account.name, + self.account_1.name, network_1.name)) src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=network_1.id, - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, listall=True, issourcenat=True, ) diff --git a/test/integration/component/test_resource_limits.py b/test/integration/component/test_resource_limits.py index 1d876b6195f..ea79c07c376 100644 --- a/test/integration/component/test_resource_limits.py +++ b/test/integration/component/test_resource_limits.py @@ -191,25 +191,25 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.debug( "Updating instance resource limit for account: %s" % - self.account_1.account.name) + self.account_1.name) # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, 0, # Instance - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, max=1 ) self.debug( "Deploying VM instance in account: %s" % - self.account_1.account.name) + self.account_1.name) virtual_machine = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, - accountid=self.account_1.account.name, - domainid=self.account_1.account.domainid, + accountid=self.account_1.name, + domainid=self.account_1.domainid, serviceofferingid=self.service_offering.id ) self.cleanup.append(virtual_machine) @@ -227,20 +227,20 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.apiclient, self.services["server"], templateid=self.template.id, - accountid=self.account_1.account.name, - domainid=self.account_1.account.domainid, + accountid=self.account_1.name, + domainid=self.account_1.domainid, serviceofferingid=self.service_offering.id ) self.debug( "Deploying VM instance in account: %s" % - self.account_2.account.name) + self.account_2.name) # Start 2 instances for account_2 virtual_machine_1 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, - accountid=self.account_2.account.name, - domainid=self.account_2.account.domainid, + accountid=self.account_2.name, + domainid=self.account_2.domainid, serviceofferingid=self.service_offering.id ) self.cleanup.append(virtual_machine_1) @@ -253,13 +253,13 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.debug( "Deploying VM instance in account: %s" % - self.account_2.account.name) + self.account_2.name) virtual_machine_2 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, - accountid=self.account_2.account.name, - domainid=self.account_2.account.domainid, + accountid=self.account_2.name, + domainid=self.account_2.domainid, serviceofferingid=self.service_offering.id ) self.cleanup.append(virtual_machine_2) @@ -287,25 +287,25 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.debug( "Updating public IP resource limit for account: %s" % - self.account_1.account.name) + self.account_1.name) # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, 1, # Public Ip - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, max=2 ) self.debug( "Deploying VM instance in account: %s" % - self.account_1.account.name) + self.account_1.name) virtual_machine_1 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, - accountid=self.account_1.account.name, - domainid=self.account_1.account.domainid, + accountid=self.account_1.name, + domainid=self.account_1.domainid, serviceofferingid=self.service_offering.id ) self.cleanup.append(virtual_machine_1) @@ -318,14 +318,14 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.debug( "Deploying VM instance in account: %s" % - self.account_2.account.name) + self.account_2.name) # Create VM for second account virtual_machine_2 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, - accountid=self.account_2.account.name, - domainid=self.account_2.account.domainid, + accountid=self.account_2.name, + domainid=self.account_2.domainid, serviceofferingid=self.service_offering.id ) self.cleanup.append(virtual_machine_2) @@ -431,25 +431,25 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.debug( "Updating public IP resource limit for account: %s" % - self.account_1.account.name) + self.account_1.name) # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, 3, # Snapshot - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, max=1 ) self.debug( "Deploying VM instance in account: %s" % - self.account_1.account.name) + self.account_1.name) virtual_machine_1 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, - accountid=self.account_1.account.name, - domainid=self.account_1.account.domainid, + accountid=self.account_1.name, + domainid=self.account_1.domainid, serviceofferingid=self.service_offering.id ) self.cleanup.append(virtual_machine_1) @@ -462,14 +462,14 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.debug( "Deploying VM instance in account: %s" % - self.account_1.account.name) + self.account_1.name) # Create VM for second account virtual_machine_2 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, - accountid=self.account_2.account.name, - domainid=self.account_2.account.domainid, + accountid=self.account_2.name, + domainid=self.account_2.domainid, serviceofferingid=self.service_offering.id ) self.cleanup.append(virtual_machine_2) @@ -498,8 +498,8 @@ class TestResourceLimitsAccount(cloudstackTestCase): # Create a snapshot from the ROOTDISK (Account 1) snapshot_1 = Snapshot.create(self.apiclient, volumes[0].id, - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, ) self.cleanup.append(snapshot_1) # Verify Snapshot state @@ -516,8 +516,8 @@ class TestResourceLimitsAccount(cloudstackTestCase): with self.assertRaises(Exception): Snapshot.create(self.apiclient, volumes[0].id, - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, ) # Get the Root disk of VM @@ -538,8 +538,8 @@ class TestResourceLimitsAccount(cloudstackTestCase): # Create a snapshot from the ROOTDISK (Account 2) snapshot_2 = Snapshot.create(self.apiclient, volumes[0].id, - account=self.account_2.account.name, - domainid=self.account_2.account.domainid, + account=self.account_2.name, + domainid=self.account_2.domainid, ) self.cleanup.append(snapshot_2) # Verify Snapshot state @@ -556,8 +556,8 @@ class TestResourceLimitsAccount(cloudstackTestCase): # Create a second snapshot from the ROOTDISK (Account 2) snapshot_3 = Snapshot.create(self.apiclient, volumes[0].id, - account=self.account_2.account.name, - domainid=self.account_2.account.domainid, + account=self.account_2.name, + domainid=self.account_2.domainid, ) self.cleanup.append(snapshot_3) # Verify Snapshot state @@ -587,25 +587,25 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.debug( "Updating volume resource limit for account: %s" % - self.account_1.account.name) + self.account_1.name) # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, 2, # Volume - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, max=2 ) self.debug( - "Deploying VM for account: %s" % self.account_1.account.name) + "Deploying VM for account: %s" % self.account_1.name) virtual_machine_1 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, - accountid=self.account_1.account.name, - domainid=self.account_1.account.domainid, + accountid=self.account_1.name, + domainid=self.account_1.domainid, serviceofferingid=self.service_offering.id ) self.cleanup.append(virtual_machine_1) @@ -617,15 +617,15 @@ class TestResourceLimitsAccount(cloudstackTestCase): ) self.debug( - "Deploying VM for account: %s" % self.account_2.account.name) + "Deploying VM for account: %s" % self.account_2.name) # Create VM for second account virtual_machine_2 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, - accountid=self.account_2.account.name, - domainid=self.account_2.account.domainid, + accountid=self.account_2.name, + domainid=self.account_2.domainid, serviceofferingid=self.service_offering.id ) self.cleanup.append(virtual_machine_2) @@ -637,13 +637,13 @@ class TestResourceLimitsAccount(cloudstackTestCase): ) self.debug( - "Create a data volume for account: %s" % self.account_1.account.name) + "Create a data volume for account: %s" % self.account_1.name) volume_1 = Volume.create( self.apiclient, self.services["volume"], zoneid=self.zone.id, - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, diskofferingid=self.disk_offering.id ) self.cleanup.append(volume_1) @@ -663,20 +663,20 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.apiclient, self.services["volume"], zoneid=self.zone.id, - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, diskofferingid=self.disk_offering.id ) self.debug( - "Create a data volume for account: %s" % self.account_2.account.name) + "Create a data volume for account: %s" % self.account_2.name) # Create volume for Account 2 volume_2 = Volume.create( self.apiclient, self.services["volume"], zoneid=self.zone.id, - account=self.account_2.account.name, - domainid=self.account_2.account.domainid, + account=self.account_2.name, + domainid=self.account_2.domainid, diskofferingid=self.disk_offering.id ) self.cleanup.append(volume_2) @@ -691,14 +691,14 @@ class TestResourceLimitsAccount(cloudstackTestCase): ) self.debug( - "Create a data volume for account: %s" % self.account_2.account.name) + "Create a data volume for account: %s" % self.account_2.name) # Create a second volume from the ROOTDISK (Account 2) volume_3 = Volume.create( self.apiclient, self.services["volume"], zoneid=self.zone.id, - account=self.account_2.account.name, - domainid=self.account_2.account.domainid, + account=self.account_2.name, + domainid=self.account_2.domainid, diskofferingid=self.disk_offering.id ) self.cleanup.append(volume_3) @@ -727,25 +727,25 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.debug( "Updating template resource limit for account: %s" % - self.account_1.account.name) + self.account_1.name) # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, 4, # Template - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, max=1 ) self.debug( "Updating volume resource limit for account: %s" % - self.account_1.account.name) + self.account_1.name) virtual_machine_1 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, - accountid=self.account_1.account.name, - domainid=self.account_1.account.domainid, + accountid=self.account_1.name, + domainid=self.account_1.domainid, serviceofferingid=self.service_offering.id ) self.cleanup.append(virtual_machine_1) @@ -758,14 +758,14 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.debug( "Deploying virtual machine for account: %s" % - self.account_2.account.name) + self.account_2.name) # Create VM for second account virtual_machine_2 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, - accountid=self.account_2.account.name, - domainid=self.account_2.account.domainid, + accountid=self.account_2.name, + domainid=self.account_2.domainid, serviceofferingid=self.service_offering.id ) self.cleanup.append(virtual_machine_2) @@ -798,8 +798,8 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.apiclient, self.services["template"], volumeid=volume.id, - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, ) self.cleanup.append(template_1) @@ -816,8 +816,8 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.apiclient, self.services["template"], volumeid=volume.id, - account=self.account_1.account.name, - domainid=self.account_1.account.domainid, + account=self.account_1.name, + domainid=self.account_1.domainid, ) virtual_machine_2.stop(self.apiclient) # Get the Root disk of VM @@ -841,8 +841,8 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.apiclient, self.services["template"], volumeid=volume.id, - account=self.account_2.account.name, - domainid=self.account_2.account.domainid, + account=self.account_2.name, + domainid=self.account_2.domainid, ) self.cleanup.append(template_2) @@ -859,8 +859,8 @@ class TestResourceLimitsAccount(cloudstackTestCase): self.apiclient, self.services["template"], volumeid=volume.id, - account=self.account_2.account.name, - domainid=self.account_2.account.domainid, + account=self.account_2.name, + domainid=self.account_2.domainid, ) self.cleanup.append(template_3) diff --git a/test/integration/component/test_storage_motion.py b/test/integration/component/test_storage_motion.py index c05d79e6861..cf110d34e61 100644 --- a/test/integration/component/test_storage_motion.py +++ b/test/integration/component/test_storage_motion.py @@ -178,6 +178,12 @@ class TestStorageMotion(cloudstackTestCase): # Migrate to a host that requires storage motion hosts[:] = [host for host in hosts if host.requiresStorageMotion] + self.assert_(hosts is not None, msg="No valid hosts for storage motion") + self.assert_(len(hosts)>0, msg="No valid hosts for storage motion. Skipping") + if hosts is None or len(hosts) == 0: + self.skipTest("No valid hosts for storage motion. Skipping") + + host = hosts[0] self.debug("Migrating VM-ID: %s to Host: %s" % ( self.virtual_machine.id, diff --git a/test/integration/component/test_vm_passwdenabled.py b/test/integration/component/test_vm_passwdenabled.py index 65b068dc2d2..e89253c407a 100644 --- a/test/integration/component/test_vm_passwdenabled.py +++ b/test/integration/component/test_vm_passwdenabled.py @@ -83,7 +83,7 @@ class TestVMPasswordEnabled(cloudstackTestCase): # Get Zone, Domain and templates domain = get_domain(cls.api_client, cls.services) zone = get_zone(cls.api_client, cls.services) - cls.services['mode'] = cls.zone.networktype + cls.services['mode'] = zone.networktype template = get_template( cls.api_client, zone.id, From e26081731898e2b3de53fdfb9f58d6fdb017f09f Mon Sep 17 00:00:00 2001 From: Saksham Srivastava Date: Tue, 14 May 2013 10:39:20 +0530 Subject: [PATCH 25/36] CLOUDSTACK-2130: UpdateDefaultNicForVirtualMachine api should also create usage events for updating new default network Signed-off-by: Mice Xia --- server/src/com/cloud/vm/UserVmManagerImpl.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 8b1a9af0341..f2c44a419da 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -1024,6 +1024,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use throw new CloudRuntimeException("Failed to find a nic profile for the existing default network. This is bad and probably means some sort of configuration corruption"); } + Network oldDefaultNetwork = null; + oldDefaultNetwork = _networkModel.getDefaultNetworkForVm(vmId); + long oldNetworkOfferingId = -1L; + + if(oldDefaultNetwork!=null) { + oldNetworkOfferingId = oldDefaultNetwork.getNetworkOfferingId(); + } NicVO existingVO = _nicDao.findById(existing.id); Integer chosenID = nic.getDeviceId(); Integer existingID = existing.getDeviceId(); @@ -1055,6 +1062,16 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use throw new CloudRuntimeException("Failed to change default nic to " + nic + " and now we have no default"); } else if (newdefault.getId() == nic.getNetworkId()) { s_logger.debug("successfully set default network to " + network + " for " + vmInstance); + String nicIdString = Long.toString(nic.getId()); + long newNetworkOfferingId = network.getNetworkOfferingId(); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), + vmInstance.getId(), nicIdString, oldNetworkOfferingId, null, 1L, VirtualMachine.class.getName(), vmInstance.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmInstance.getAccountId(), vmInstance.getDataCenterId(), + vmInstance.getId(), nicIdString, newNetworkOfferingId, null, 1L, VirtualMachine.class.getName(), vmInstance.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), + vmInstance.getId(), nicIdString, newNetworkOfferingId, null, 0L, VirtualMachine.class.getName(), vmInstance.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmInstance.getAccountId(), vmInstance.getDataCenterId(), + vmInstance.getId(), nicIdString, oldNetworkOfferingId, null, 0L, VirtualMachine.class.getName(), vmInstance.getUuid()); return _vmDao.findById(vmInstance.getId()); } From e7fef86c8086a3bad3a5f3aacaa39dd5ddef3ab4 Mon Sep 17 00:00:00 2001 From: Mice Xia Date: Thu, 16 May 2013 15:19:05 +0800 Subject: [PATCH 26/36] CLOUDSTACK-2456 usage:usage parser throws runtime exception while parsing networkoffering usage --- .../com/cloud/usage/dao/UsageNetworkOfferingDaoImpl.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/schema/src/com/cloud/usage/dao/UsageNetworkOfferingDaoImpl.java b/engine/schema/src/com/cloud/usage/dao/UsageNetworkOfferingDaoImpl.java index c3fc5a6f6c1..4ed7c27d491 100644 --- a/engine/schema/src/com/cloud/usage/dao/UsageNetworkOfferingDaoImpl.java +++ b/engine/schema/src/com/cloud/usage/dao/UsageNetworkOfferingDaoImpl.java @@ -118,18 +118,18 @@ public class UsageNetworkOfferingDaoImpl extends GenericDaoBase Date: Thu, 16 May 2013 16:00:02 +0800 Subject: [PATCH 27/36] instead of using '==', use equals() to test Long value equality --- server/src/com/cloud/api/ApiDispatcher.java | 2 +- server/src/com/cloud/api/query/QueryManagerImpl.java | 2 +- server/src/com/cloud/capacity/CapacityManagerImpl.java | 2 +- .../AgentBasedStandaloneConsoleProxyManager.java | 2 +- server/src/com/cloud/network/NetworkServiceImpl.java | 2 +- server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java | 4 ++-- server/src/com/cloud/server/ManagementServerImpl.java | 6 +++--- server/src/com/cloud/template/TemplateManagerImpl.java | 6 +++--- server/src/com/cloud/vm/UserVmManagerImpl.java | 2 +- server/src/com/cloud/vm/VirtualMachineManagerImpl.java | 2 +- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/server/src/com/cloud/api/ApiDispatcher.java b/server/src/com/cloud/api/ApiDispatcher.java index b4437ce6193..b7d08e2c872 100755 --- a/server/src/com/cloud/api/ApiDispatcher.java +++ b/server/src/com/cloud/api/ApiDispatcher.java @@ -168,7 +168,7 @@ public class ApiDispatcher { pageSize = Long.valueOf((String) pageSizeObj); } - if ((unpackedParams.get(ApiConstants.PAGE) == null) && (pageSize != null && pageSize != BaseListCmd.PAGESIZE_UNLIMITED)) { + if ((unpackedParams.get(ApiConstants.PAGE) == null) && (pageSize != null && !pageSize.equals(BaseListCmd.PAGESIZE_UNLIMITED))) { ServerApiException ex = new ServerApiException(ApiErrorCode.PARAM_ERROR, "\"page\" parameter is required when \"pagesize\" is specified"); ex.setCSErrorCode(CSExceptionErrorCode.getCSErrCode(ex.getClass().getName())); throw ex; diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index 9872c3a53ef..a126925e5f0 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -2346,7 +2346,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // offerings private boolean isPermissible(Long accountDomainId, Long offeringDomainId) { - if (accountDomainId == offeringDomainId) { + if (accountDomainId.equals(offeringDomainId)) { return true; // account and service offering in same domain } diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index 1eb2fa5894a..e7101c6755b 100755 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -681,7 +681,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, if ((newState == State.Starting || newState == State.Migrating || event == Event.AgentReportMigrated) && vm.getHostId() != null) { boolean fromLastHost = false; - if (vm.getLastHostId() == vm.getHostId()) { + if (vm.getLastHostId().equals(vm.getHostId())) { s_logger.debug("VM starting again on the last host it was stopped on"); fromLastHost = true; } diff --git a/server/src/com/cloud/consoleproxy/AgentBasedStandaloneConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/AgentBasedStandaloneConsoleProxyManager.java index 3cfdf22bf08..23663334dbd 100644 --- a/server/src/com/cloud/consoleproxy/AgentBasedStandaloneConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/AgentBasedStandaloneConsoleProxyManager.java @@ -57,7 +57,7 @@ AgentBasedConsoleProxyManager { if (allocatedHost == null) { /*Is there a consoleproxy agent running in the same pod?*/ for (HostVO hv : hosts) { - if (hv.getType() == Host.Type.ConsoleProxy && hv.getPodId() == host.getPodId()) { + if (hv.getType() == Host.Type.ConsoleProxy && hv.getPodId().equals(host.getPodId())) { allocatedHost = hv; break; } diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 2bc3913a99e..ed9a8c4ece7 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -1264,7 +1264,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { throw new InvalidParameterValueException("Unable to find specified NetworkACL"); } - if(vpcId != acl.getVpcId()){ + if(!vpcId.equals(acl.getVpcId())){ throw new InvalidParameterValueException("ACL: "+aclId+" do not belong to the VPC"); } } diff --git a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java index 00c90d5164e..4d5d98192fa 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -182,7 +182,7 @@ public class NetworkACLServiceImpl extends ManagerBase implements NetworkACLServ throw new InvalidParameterValueException("Unable to find Vpc associated with the NetworkACL"); } _accountMgr.checkAccess(caller, null, true, vpc); - if(gateway.getVpcId() != acl.getVpcId()){ + if(!gateway.getVpcId().equals(acl.getVpcId())){ throw new InvalidParameterValueException("private gateway: "+privateGatewayId+" and ACL: "+aclId+" do not belong to the same VPC"); } } @@ -225,7 +225,7 @@ public class NetworkACLServiceImpl extends ManagerBase implements NetworkACLServ } _accountMgr.checkAccess(caller, null, true, vpc); - if(network.getVpcId() != acl.getVpcId()){ + if(!network.getVpcId().equals(acl.getVpcId())){ throw new InvalidParameterValueException("Network: "+networkId+" and ACL: "+aclId+" do not belong to the same VPC"); } } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 137f07e1527..bc3728203bc 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1152,7 +1152,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (volumePools.isEmpty()) { allHosts.remove(host); } else { - if (host.getClusterId() != srcHost.getClusterId() || usesLocal) { + if (!host.getClusterId().equals(srcHost.getClusterId()) || usesLocal) { requiresStorageMotion.put(host, true); } } @@ -1887,7 +1887,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } // Don't allow to modify system template - if (id == Long.valueOf(1)) { + if (id.equals(Long.valueOf(1))) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to update template/iso of specified id"); ex.addProxyObject(template, id, "templateId"); throw ex; @@ -2414,7 +2414,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe public int compare(SummedCapacity arg0, SummedCapacity arg1) { if (arg0.getPercentUsed() < arg1.getPercentUsed()) { return 1; - } else if (arg0.getPercentUsed() == arg1.getPercentUsed()) { + } else if (arg0.getPercentUsed().equals(arg1.getPercentUsed())) { return 0; } return -1; diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index a8729e1490a..d4976cdc357 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -993,7 +993,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } //Verify parameters - if (sourceZoneId == destZoneId) { + if (sourceZoneId.equals(destZoneId)) { throw new InvalidParameterValueException("Please specify different source and destination zones."); } @@ -1522,7 +1522,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, Account caller = UserContext.current().getCaller(); Long id = cmd.getId(); - if (id == Long.valueOf(1)) { + if (id.equals(Long.valueOf(1))) { throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id); } @@ -1614,7 +1614,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, throw new InvalidParameterValueException("unable to update permissions for " + mediaType + " with id " + id + " as it is removed "); } - if (id == Long.valueOf(1)) { + if (id.equals(Long.valueOf(1))) { throw new InvalidParameterValueException("unable to update permissions for " + mediaType + " with id " + id); } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index f2c44a419da..fe80d2cb7e6 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -3708,7 +3708,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use List vmVolumes = _volsDao.findUsableVolumesForInstance(vm.getId()); Map volToPoolObjectMap = new HashMap(); - if (!isVMUsingLocalStorage(vm) && destinationHost.getClusterId() == srcHost.getClusterId()) { + if (!isVMUsingLocalStorage(vm) && destinationHost.getClusterId().equals(srcHost.getClusterId())) { if (volumeToPool.isEmpty()) { // If the destination host is in the same cluster and volumes do not have to be migrated across pools // then fail the call. migrateVirtualMachine api should have been used. diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 521b5e0c582..d153bb2cafe 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -1322,7 +1322,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (migrationResult) { //if the vm is migrated to different pod in basic mode, need to reallocate ip - if (vm.getPodIdToDeployIn() != destPool.getPodId()) { + if (!vm.getPodIdToDeployIn().equals(destPool.getPodId())) { DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), destPool.getPodId(), null, null, null, null); VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, null, null, null, null); _networkMgr.reallocate(vmProfile, plan); From e26442f7d0abd9cf7cfefc85585fdd669af395a6 Mon Sep 17 00:00:00 2001 From: Mice Xia Date: Thu, 16 May 2013 16:18:53 +0800 Subject: [PATCH 28/36] instead of '==', use equals() to compare two strings in cloud-server --- .../src/com/cloud/configuration/ConfigurationManagerImpl.java | 2 +- server/src/com/cloud/test/DatabaseConfig.java | 4 ++-- server/src/com/cloud/vm/UserVmManagerImpl.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 96145a2d3b3..887878254b3 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -2491,7 +2491,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if ( vlans != null && vlans.size() > 0 ) { if ( vlanId == null ) { vlanId = vlan.getVlanTag(); - } else if ( vlan.getVlanTag() != vlanId ) { + } else if (!vlan.getVlanTag().equals(vlanId)) { throw new InvalidParameterValueException("there is already one vlan " + vlan.getVlanTag() + " on network :" + + network.getId() + ", only one vlan is allowed on guest network"); } diff --git a/server/src/com/cloud/test/DatabaseConfig.java b/server/src/com/cloud/test/DatabaseConfig.java index 7c10f98abf4..70c81781959 100755 --- a/server/src/com/cloud/test/DatabaseConfig.java +++ b/server/src/com/cloud/test/DatabaseConfig.java @@ -792,14 +792,14 @@ public class DatabaseConfig { } // If a netmask was provided, check that the startIP, endIP, and gateway all belong to the same subnet - if (netmask != null && netmask != "") { + if (netmask != null && !netmask.equals("")) { if (endIP != null) { if (!IPRangeConfig.sameSubnet(startIP, endIP, netmask)) { printError("Start and end IPs for the public IP range must be in the same subnet, as per the provided netmask."); } } - if (gateway != null && gateway != "") { + if (gateway != null && !gateway.equals("")) { if (!IPRangeConfig.sameSubnet(startIP, gateway, netmask)) { printError("The start IP for the public IP range must be in the same subnet as the gateway, as per the provided netmask."); } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index fe80d2cb7e6..7416cae61de 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -1673,7 +1673,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use String description = ""; - if (displayName != vmInstance.getDisplayName()) { + if (!displayName.equals(vmInstance.getDisplayName())) { description += "New display name: " + displayName + ". "; } From b4903ebbead34d02ba9ee445522473467d295519 Mon Sep 17 00:00:00 2001 From: Gavin Lee Date: Thu, 16 May 2013 16:19:11 +0800 Subject: [PATCH 29/36] $PRODUCT; should be &PRODUCT; to represent entity CloudStack --- docs/en-US/build-rpm.xml | 8 ++++---- docs/en-US/deployment-architecture-overview.xml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/en-US/build-rpm.xml b/docs/en-US/build-rpm.xml index 574065833ff..7caf924bfe4 100644 --- a/docs/en-US/build-rpm.xml +++ b/docs/en-US/build-rpm.xml @@ -41,9 +41,9 @@ under the License. You probably want to ensure that your environment variables will survive a logout/reboot. Be sure to update ~/.bashrc with the PATH and JAVA_HOME variables. - Building RPMs for $PRODUCT; is fairly simple. Assuming you already have the source downloaded and have uncompressed the tarball into a local directory, you're going to be able to generate packages in just a few minutes. + Building RPMs for &PRODUCT; is fairly simple. Assuming you already have the source downloaded and have uncompressed the tarball into a local directory, you're going to be able to generate packages in just a few minutes. Packaging has Changed - If you've created packages for $PRODUCT; previously, you should be aware that the process has changed considerably since the project has moved to using Apache Maven. Please be sure to follow the steps in this section closely. + If you've created packages for &PRODUCT; previously, you should be aware that the process has changed considerably since the project has moved to using Apache Maven. Please be sure to follow the steps in this section closely.
Generating RPMS @@ -69,7 +69,7 @@ under the License. Configuring your systems to use your new yum repository Now that your yum repository is populated with RPMs and metadata - we need to configure the machines that need to install $PRODUCT;. + we need to configure the machines that need to install &PRODUCT;. Create a file named /etc/yum.repos.d/cloudstack.repo with this information: [apache-cloudstack] @@ -79,7 +79,7 @@ under the License. gpgcheck=0 - Completing this step will allow you to easily install $PRODUCT; on a number of machines across the network. + Completing this step will allow you to easily install &PRODUCT; on a number of machines across the network.
diff --git a/docs/en-US/deployment-architecture-overview.xml b/docs/en-US/deployment-architecture-overview.xml index e3103c52c1c..835898ced7f 100644 --- a/docs/en-US/deployment-architecture-overview.xml +++ b/docs/en-US/deployment-architecture-overview.xml @@ -49,7 +49,7 @@ multi-node Management Server installation and up to tens of thousands of hosts using any of several advanced networking setups. For information about deployment options, see the "Choosing a Deployment Architecture" - section of the $PRODUCT; Installation Guide. + section of the &PRODUCT; Installation Guide. From 6ae6c2b8b603fc8d44d6bec57caf765d843ca27d Mon Sep 17 00:00:00 2001 From: Gavin Lee Date: Thu, 16 May 2013 17:19:22 +0800 Subject: [PATCH 30/36] A space char needed after &PRODUCT; entity representation --- docs/en-US/event-framework.xml | 2 +- docs/en-US/gslb.xml | 2 +- docs/en-US/ipv6-support.xml | 2 +- docs/en-US/vmware-cluster-config-dvswitch.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/en-US/event-framework.xml b/docs/en-US/event-framework.xml index 88c45c9033d..0f62fac1407 100644 --- a/docs/en-US/event-framework.xml +++ b/docs/en-US/event-framework.xml @@ -24,7 +24,7 @@ Event notification framework provides a means for the Management Server components to publish and subscribe to &PRODUCT; events. Event notification is achieved by implementing the concept of event bus abstraction in the Management Server. An event bus is introduced in the - Management Server that allows the &PRODUCT;components and extension plug-ins to subscribe to the + Management Server that allows the &PRODUCT; components and extension plug-ins to subscribe to the events by using the Advanced Message Queuing Protocol (AMQP) client. In &PRODUCT;, a default implementation of event bus is provided as a plug-in that uses the RabbitMQ AMQP client. The AMQP client pushes the published events to a compatible AMQP server. Therefore all the &PRODUCT; diff --git a/docs/en-US/gslb.xml b/docs/en-US/gslb.xml index d5d2d203265..968e8e2cefa 100644 --- a/docs/en-US/gslb.xml +++ b/docs/en-US/gslb.xml @@ -45,7 +45,7 @@ A typical GSLB environment is comprised of the following components: - GSLB Site: In &PRODUCT;terminology, GSLB sites are + GSLB Site: In &PRODUCT; terminology, GSLB sites are represented by zones that are mapped to data centers, each of which has various network appliances. Each GSLB site is managed by a NetScaler appliance that is local to that site. Each of these appliances treats its own site as the local site and all other diff --git a/docs/en-US/ipv6-support.xml b/docs/en-US/ipv6-support.xml index c7f7744393e..bc14c8eab0e 100644 --- a/docs/en-US/ipv6-support.xml +++ b/docs/en-US/ipv6-support.xml @@ -21,7 +21,7 @@ -->
IPv6 Support in &PRODUCT; - &PRODUCT;supports Internet Protocol version 6 (IPv6), the recent version of the Internet + &PRODUCT; supports Internet Protocol version 6 (IPv6), the recent version of the Internet Protocol (IP) that defines routing the network traffic. IPv6 uses a 128-bit address that exponentially expands the current address space that is available to the users. IPv6 addresses consist of eight groups of four hexadecimal digits separated by colons, for example, diff --git a/docs/en-US/vmware-cluster-config-dvswitch.xml b/docs/en-US/vmware-cluster-config-dvswitch.xml index 3468c1bea4e..a3250f4f380 100644 --- a/docs/en-US/vmware-cluster-config-dvswitch.xml +++ b/docs/en-US/vmware-cluster-config-dvswitch.xml @@ -21,7 +21,7 @@ -->
Configuring a vSphere Cluster with VMware Distributed Virtual Switch - &PRODUCT;supports VMware vNetwork Distributed Switch (VDS) for virtual network configuration + &PRODUCT; supports VMware vNetwork Distributed Switch (VDS) for virtual network configuration in a VMware vSphere environment. This section helps you configure VMware VDS in a &PRODUCT; deployment. Each vCenter server instance can support up to 128 VDS instances and each VDS instance can manage up to 500 VMware hosts. From 3c51c4e7adb717b5cee3bd01be716d75e288aa0c Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Thu, 16 May 2013 12:26:23 +0530 Subject: [PATCH 31/36] CLOUDSTACK-2461: createGSLBRule API is failing to pick the default algorithm "round robin" for parameter "gslblbmethod" fix defaults to round robin when parameter not specified --- .../region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java index b08b6aeff17..07d3274b335 100644 --- a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java @@ -85,7 +85,11 @@ public class CreateGlobalLoadBalancerRuleCmd extends BaseAsyncCreateCmd { } public String getAlgorithm() { - return algorithm; + if (algorithm != null) { + return algorithm; + } else { + return GlobalLoadBalancerRule.Algorithm.RoundRobin.name(); + } } public String getGslbMethod() { From 565d829c006609251c18883b1007175b6a1d2f79 Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Thu, 16 May 2013 14:25:14 +0530 Subject: [PATCH 32/36] CLOUDSTACK-2460: fix the event descriptions for create/delete/update/assign global load balancer rule apis --- api/src/com/cloud/event/EventTypes.java | 1 + .../AssignToGlobalLoadBalancerRuleCmd.java | 2 +- .../gslb/CreateGlobalLoadBalancerRuleCmd.java | 2 +- .../gslb/DeleteGlobalLoadBalancerRuleCmd.java | 4 +-- .../gslb/UpdateGlobalLoadBalancerRuleCmd.java | 28 +++++++++++++++---- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index d272c99bc02..e317a8fbf1c 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -134,6 +134,7 @@ public class EventTypes { public static final String EVENT_REMOVE_FROM_GLOBAL_LOAD_BALANCER_RULE = "GLOBAL.LB.REMOVE"; public static final String EVENT_GLOBAL_LOAD_BALANCER_CREATE = "GLOBAL.LB.CREATE"; public static final String EVENT_GLOBAL_LOAD_BALANCER_DELETE = "GLOBAL.LB.DELETE"; + public static final String EVENT_GLOBAL_LOAD_BALANCER_UPDATE = "GLOBAL.LB.UPDATE"; // Account events public static final String EVENT_ACCOUNT_ENABLE = "ACCOUNT.ENABLE"; diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java index 1c07a0aad53..1575cd34d07 100644 --- a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java @@ -95,7 +95,7 @@ public class AssignToGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { @Override public String getEventDescription() { - return "applying load balancer rules " + StringUtils.join(getLoadBalancerRulesIds(), ",") + + return "assign load balancer rules " + StringUtils.join(getLoadBalancerRulesIds(), ",") + " to global load balancer rule " + getGlobalLoadBalancerRuleId(); } diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java index 07d3274b335..ac3349516df 100644 --- a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java @@ -162,7 +162,7 @@ public class CreateGlobalLoadBalancerRuleCmd extends BaseAsyncCreateCmd { @Override public String getEventDescription() { - return "creating a global load balancer: " + getName() + " for account: " + getAccountName(); + return "creating a global load balancer rule Id: " + getEntityId(); } diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java index 424b1072887..fe5decdf5fc 100644 --- a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java @@ -77,12 +77,12 @@ public class DeleteGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { @Override public String getEventType() { - return EventTypes.EVENT_LOAD_BALANCER_DELETE; + return EventTypes.EVENT_GLOBAL_LOAD_BALANCER_DELETE; } @Override public String getEventDescription() { - return "deleting global load balancer: " + getGlobalLoadBalancerId(); + return "deleting global load balancer rule: " + getGlobalLoadBalancerId(); } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/UpdateGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/UpdateGlobalLoadBalancerRuleCmd.java index 10694e1633e..4e2c0fd0fb9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/UpdateGlobalLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/UpdateGlobalLoadBalancerRuleCmd.java @@ -17,11 +17,11 @@ package org.apache.cloudstack.api.command.user.region.ha.gslb; +import com.cloud.event.EventTypes; +import com.cloud.region.ha.GlobalLoadBalancerRule; import com.cloud.region.ha.GlobalLoadBalancingRulesService; -import org.apache.cloudstack.api.APICommand; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; -import org.apache.cloudstack.api.Parameter; +import com.cloud.user.Account; +import org.apache.cloudstack.api.*; import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse; import org.apache.cloudstack.api.response.LoadBalancerResponse; import org.apache.log4j.Logger; @@ -29,7 +29,7 @@ import org.apache.log4j.Logger; import javax.inject.Inject; @APICommand(name = "updateGlobalLoadBalancerRule", description = "update global load balancer rules.", responseObject = LoadBalancerResponse.class) -public class UpdateGlobalLoadBalancerRuleCmd extends BaseListTaggedResourcesCmd { +public class UpdateGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(GlobalLoadBalancerResponse.class.getName()); private static final String s_name = "updategloballoadbalancerruleresponse"; @@ -88,9 +88,27 @@ public class UpdateGlobalLoadBalancerRuleCmd extends BaseListTaggedResourcesCmd return s_name; } + @Override + public long getEntityOwnerId() { + GlobalLoadBalancerRule lb = _entityMgr.findById(GlobalLoadBalancerRule.class, getId()); + if (lb != null) { + return lb.getAccountId(); + } + return Account.ACCOUNT_ID_SYSTEM; + } + @Override public void execute() { _gslbService.updateGlobalLoadBalancerRule(this); } + @Override + public String getEventType() { + return EventTypes.EVENT_GLOBAL_LOAD_BALANCER_UPDATE; + } + + @Override + public String getEventDescription() { + return null; + } } From d2d0398e3321b819756a537c0b1fab0491e5a3e6 Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Thu, 16 May 2013 14:45:49 +0530 Subject: [PATCH 33/36] CLOUDSTACK-2529: GlobalLoadBalancerResponse should have the full FQDN for the global load balanced service --- server/src/com/cloud/api/ApiDBUtils.java | 5 +++++ server/src/com/cloud/api/ApiResponseHelper.java | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 94c873ee9fb..1afedac5144 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -1668,4 +1668,9 @@ public class ApiDBUtils { public static List listSiteLoadBalancers(long gslbRuleId) { return _gslbService.listSiteLoadBalancers(gslbRuleId); } + + public static String getDnsNameConfiguredForGslb() { + String providerDnsName = _configDao.getValue(Config.CloudDnsName.key()); + return providerDnsName; + } } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 9a70d95e0bc..482594dd8f1 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -787,7 +787,8 @@ public class ApiResponseHelper implements ResponseGenerator { response.setAlgorithm(globalLoadBalancerRule.getAlgorithm()); response.setStickyMethod(globalLoadBalancerRule.getPersistence()); response.setServiceType(globalLoadBalancerRule.getServiceType()); - response.setServiceDomainName(globalLoadBalancerRule.getGslbDomain()); + response.setServiceDomainName(globalLoadBalancerRule.getGslbDomain() + "." + + ApiDBUtils.getDnsNameConfiguredForGslb()); response.setName(globalLoadBalancerRule.getName()); response.setDescription(globalLoadBalancerRule.getDescription()); response.setRegionIdId(globalLoadBalancerRule.getRegion()); From 33e683915c3083ac60a578fc90a7d90a64cb028e Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Thu, 16 May 2013 15:18:02 +0530 Subject: [PATCH 34/36] CLOUDSTACK-2462: Failed to create GSLB rule with "proximity" algorithm add RTT as load balancing method for GSLB vserver --- .../com/cloud/network/resource/NetscalerResource.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java index 98e14618248..c0d4599dc0c 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java @@ -1095,7 +1095,15 @@ public class NetscalerResource implements ServerResource { } vserver.set_name(vserverName); - vserver.set_lbmethod(lbMethod); + if ("RoundRobin".equalsIgnoreCase(lbMethod)) { + vserver.set_lbmethod("ROUNDROBIN"); + } else if ("LeastConn".equalsIgnoreCase(lbMethod)) { + vserver.set_lbmethod("LEASTCONNECTION"); + } else if ("Proximity".equalsIgnoreCase(lbMethod)) { + vserver.set_lbmethod("RTT"); + } else { + throw new ExecutionException("Unsupported LB method"); + } vserver.set_persistencetype(persistenceType); if ("SOURCEIP".equalsIgnoreCase(persistenceType)) { vserver.set_persistenceid(persistenceId); From f441582e1b7747bba1385ecb48a7b7b34a9dded1 Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Thu, 16 May 2013 18:26:14 +0530 Subject: [PATCH 35/36] CLOUDSTACK-2378: assignToGSLBRule or removeFromGlobalLoadBalancerRule APIs are failing when there are multiple physical network in a zone adding support for deployments where multiple physical networks are configured for guest traffic in a zone --- .../network/element/NetscalerElement.java | 39 ++++++++++++------- .../GlobalLoadBalancingRulesServiceImpl.java | 37 ++++++++++-------- .../region/gslb/GslbServiceProvider.java | 8 ++-- ...obalLoadBalancingRulesServiceImplTest.java | 3 ++ 4 files changed, 52 insertions(+), 35 deletions(-) diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java index cc2bcc17a43..850962d05ee 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java @@ -923,13 +923,13 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl } @Override - public boolean applyGlobalLoadBalancerRule(long zoneId, GlobalLoadBalancerConfigCommand gslbConfigCmd) + public boolean applyGlobalLoadBalancerRule(long zoneId, long physicalNetworkId, GlobalLoadBalancerConfigCommand gslbConfigCmd) throws ResourceUnavailableException { long zoneGslbProviderHosId = 0; // find the NetScaler device configured as gslb service provider in the zone - ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId); + ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId, physicalNetworkId); if (nsGslbProvider == null) { String msg = "Unable to find a NetScaler configured as gslb service provider in zone " + zoneId; s_logger.debug(msg); @@ -950,28 +950,37 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl return true; } - private ExternalLoadBalancerDeviceVO findGslbProvider(long zoneId) { + private ExternalLoadBalancerDeviceVO findGslbProvider(long zoneId, long physicalNetworkId) { List pNtwks = _physicalNetworkDao.listByZoneAndTrafficType(zoneId, TrafficType.Guest); - if (pNtwks.isEmpty() || pNtwks.size() > 1) { - throw new InvalidParameterValueException("Unable to get physical network in zone id = " + zoneId); + + if (pNtwks == null || pNtwks.isEmpty()) { + throw new InvalidParameterValueException("Unable to get physical network: " + physicalNetworkId + + " in zone id = " + zoneId); + } else { + for (PhysicalNetwork physicalNetwork : pNtwks) { + if (physicalNetwork.getId() == physicalNetworkId) { + PhysicalNetworkVO physNetwork = pNtwks.get(0); + ExternalLoadBalancerDeviceVO nsGslbProvider = _externalLoadBalancerDeviceDao.findGslbServiceProvider( + physNetwork.getId(), Provider.Netscaler.getName()); + return nsGslbProvider; + } + } } - PhysicalNetworkVO physNetwork = pNtwks.get(0); - ExternalLoadBalancerDeviceVO nsGslbProvider = _externalLoadBalancerDeviceDao.findGslbServiceProvider( - physNetwork.getId(), Provider.Netscaler.getName()); - return nsGslbProvider; + + return null; } @Override - public boolean isServiceEnabledInZone(long zoneId) { + public boolean isServiceEnabledInZone(long zoneId, long physicalNetworkId) { - ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId); + ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId, physicalNetworkId); //return true if a NetScaler device is configured in the zone return (nsGslbProvider != null); } @Override - public String getZoneGslbProviderPublicIp(long zoneId) { - ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId); + public String getZoneGslbProviderPublicIp(long zoneId, long physicalNetworkId) { + ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId, physicalNetworkId); if (nsGslbProvider != null) { return nsGslbProvider.getGslbSitePublicIP(); } @@ -979,8 +988,8 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl } @Override - public String getZoneGslbProviderPrivateIp(long zoneId) { - ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId); + public String getZoneGslbProviderPrivateIp(long zoneId, long physicalNetworkId) { + ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId, physicalNetworkId); if (nsGslbProvider != null) { return nsGslbProvider.getGslbSitePrivateIP(); } diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java index 56c46b01c79..0622f77f750 100644 --- a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java @@ -35,6 +35,7 @@ import com.cloud.region.ha.GlobalLoadBalancingRulesService; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.UserContext; +import com.cloud.utils.Pair; import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; @@ -173,6 +174,7 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR List oldLbRuleIds = new ArrayList(); List oldZones = new ArrayList(); List newZones = new ArrayList(oldZones); + List> physcialNetworks = new ArrayList>(); // get the list of load balancer rules id's that are assigned currently to GSLB rule and corresponding zone id's List gslbLbMapVos = _gslbLbMapDao.listByGslbRuleId(gslbRuleId); @@ -217,12 +219,14 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR } newZones.add(network.getDataCenterId()); + physcialNetworks.add(new Pair(network.getDataCenterId(), network.getPhysicalNetworkId())); } - // check each of the zone has a GSLB service provider configured - for (Long zoneId: newZones) { - if (!checkGslbServiceEnabledInZone(zoneId)) { - throw new InvalidParameterValueException("GSLB service is not enabled in the Zone"); + // for each of the physical network check if GSLB service provider configured + for (Pair physicalNetwork: physcialNetworks) { + if (!checkGslbServiceEnabledInZone(physicalNetwork.first(), physicalNetwork.second())) { + throw new InvalidParameterValueException("GSLB service is not enabled in the Zone:" + + physicalNetwork.first() + " and physical network " + physicalNetwork.second()); } } @@ -543,8 +547,8 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR GlobalLoadBalancerConfigCommand gslbConfigCmd = new GlobalLoadBalancerConfigCommand(gslbFqdn, lbMethod, persistenceMethod, serviceType, gslbRuleId, revoke); - // list of the zones participating in global load balancing - List gslbSiteIds = new ArrayList(); + // list of the physical network participating in global load balancing + List> gslbSiteIds = new ArrayList>(); // map of the zone and info corresponding to the load balancer configured in the zone Map zoneSiteLoadbalancerMap = new HashMap(); @@ -559,37 +563,38 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR LoadBalancerVO loadBalancer = _lbDao.findById(gslbLbMapVo.getLoadBalancerId()); Network network = _networkDao.findById(loadBalancer.getNetworkId()); long dataCenterId = network.getDataCenterId(); + long physicalNetworkId = network.getPhysicalNetworkId(); - gslbSiteIds.add(dataCenterId); + gslbSiteIds.add(new Pair(dataCenterId, physicalNetworkId)); IPAddressVO ip = _ipAddressDao.findById(loadBalancer.getSourceIpAddressId()); SiteLoadBalancerConfig siteLb = new SiteLoadBalancerConfig(gslbLbMapVo.isRevoke(), serviceType, ip.getAddress().addr(), Integer.toString(loadBalancer.getDefaultPortStart()), dataCenterId); - siteLb.setGslbProviderPublicIp(_gslbProvider.getZoneGslbProviderPublicIp(dataCenterId)); - siteLb.setGslbProviderPrivateIp(_gslbProvider.getZoneGslbProviderPrivateIp(dataCenterId)); + siteLb.setGslbProviderPublicIp(_gslbProvider.getZoneGslbProviderPublicIp(dataCenterId, physicalNetworkId)); + siteLb.setGslbProviderPrivateIp(_gslbProvider.getZoneGslbProviderPrivateIp(dataCenterId, physicalNetworkId)); zoneSiteLoadbalancerMap.put(network.getDataCenterId(), siteLb); } // loop through all the zones, participating in GSLB, and send GSLB config command // to the corresponding GSLB service provider in that zone - for (long zoneId: gslbSiteIds) { + for (Pair zoneId: gslbSiteIds) { List slbs = new ArrayList(); // set site as 'local' for the site in that zone - for (long innerLoopZoneId: gslbSiteIds) { - SiteLoadBalancerConfig siteLb = zoneSiteLoadbalancerMap.get(innerLoopZoneId); - siteLb.setLocal(zoneId == innerLoopZoneId); + for (Pair innerLoopZoneId: gslbSiteIds) { + SiteLoadBalancerConfig siteLb = zoneSiteLoadbalancerMap.get(innerLoopZoneId.first()); + siteLb.setLocal(zoneId.first() == innerLoopZoneId.first()); slbs.add(siteLb); } gslbConfigCmd.setSiteLoadBalancers(slbs); try { - _gslbProvider.applyGlobalLoadBalancerRule(zoneId, gslbConfigCmd); + _gslbProvider.applyGlobalLoadBalancerRule(zoneId.first(), zoneId.second(), gslbConfigCmd); } catch (ResourceUnavailableException e) { s_logger.warn("Failed to configure GSLB rul in the zone " + zoneId + " due to " + e.getMessage()); throw new CloudRuntimeException("Failed to configure GSLB rul in the zone"); @@ -599,13 +604,13 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR return true; } - private boolean checkGslbServiceEnabledInZone(long zoneId) { + private boolean checkGslbServiceEnabledInZone(long zoneId, long physicalNetworkId) { if (_gslbProvider == null) { throw new CloudRuntimeException("No GSLB provider is available"); } - return _gslbProvider.isServiceEnabledInZone(zoneId); + return _gslbProvider.isServiceEnabledInZone(zoneId, physicalNetworkId); } @Override diff --git a/server/src/org/apache/cloudstack/region/gslb/GslbServiceProvider.java b/server/src/org/apache/cloudstack/region/gslb/GslbServiceProvider.java index 4338d65eff2..0413edff978 100755 --- a/server/src/org/apache/cloudstack/region/gslb/GslbServiceProvider.java +++ b/server/src/org/apache/cloudstack/region/gslb/GslbServiceProvider.java @@ -24,13 +24,13 @@ import org.apache.cloudstack.region.RegionServiceProvider; public interface GslbServiceProvider extends RegionServiceProvider { - public boolean isServiceEnabledInZone(long zoneId); + public boolean isServiceEnabledInZone(long zoneId, long physicalNetworkId); - public String getZoneGslbProviderPublicIp(long zoneId); + public String getZoneGslbProviderPublicIp(long zoneId, long physicalNetworkId); - public String getZoneGslbProviderPrivateIp(long zoneId); + public String getZoneGslbProviderPrivateIp(long zoneId, long physicalNetworkId); - public boolean applyGlobalLoadBalancerRule(long zoneId, GlobalLoadBalancerConfigCommand gslbConfigCmd) + public boolean applyGlobalLoadBalancerRule(long zoneId, long physicalNetworkId, GlobalLoadBalancerConfigCommand gslbConfigCmd) throws ResourceUnavailableException; } diff --git a/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java b/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java index 700fe8f7dde..1c281a08bed 100644 --- a/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java +++ b/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java @@ -730,6 +730,9 @@ public class GlobalLoadBalancingRulesServiceImplTest extends TestCase { Field dcID = NetworkVO.class.getDeclaredField("dataCenterId"); dcID.setAccessible(true); dcID.set(networkVo, new Long(1)); + Field phyNetworkId = NetworkVO.class.getDeclaredField("physicalNetworkId"); + phyNetworkId.setAccessible(true); + phyNetworkId.set(networkVo, new Long(200)); when(gslbServiceImpl._networkDao.findById(new Long(1))).thenReturn(networkVo); GlobalLoadBalancerLbRuleMapVO gslbLbMap = new GlobalLoadBalancerLbRuleMapVO(1, 1); From d078f921671d0f28d9291fa2bffa8a7eab53cda7 Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Thu, 16 May 2013 19:12:42 +0530 Subject: [PATCH 36/36] CLOUDSTACK-2544: Fix NPE while comparing lastHostId during capacity calculation --- server/src/com/cloud/capacity/CapacityManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index e7101c6755b..b2419893cf7 100755 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -681,7 +681,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, if ((newState == State.Starting || newState == State.Migrating || event == Event.AgentReportMigrated) && vm.getHostId() != null) { boolean fromLastHost = false; - if (vm.getLastHostId().equals(vm.getHostId())) { + if (vm.getHostId().equals(vm.getLastHostId())) { s_logger.debug("VM starting again on the last host it was stopped on"); fromLastHost = true; }