diff --git a/.project b/.project deleted file mode 100644 index 183860bd142..00000000000 --- a/.project +++ /dev/null @@ -1,24 +0,0 @@ - - - mgit - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - - - src - 2 - /Users/john1/mgit/cloudbridge/src - - - diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index 7b0f264f46b..eda69df3ed6 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -1,4 +1,5 @@ #new labels (begin) ********************************************************************************************** +label.network.rate.megabytes=Network Rate (MB/s) label.action.enable.physical.network=Enable physical network label.action.disable.physical.network=Disable physical network message.action.enable.physical.network=Please confirm that you want to enable this physical network. 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 9c0d189046f..19f87c23e04 100755 --- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config +++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config @@ -696,11 +696,8 @@ setup_elbvm() { setup_default() { cat > /etc/network/interfaces << EOF -auto lo eth0 +auto lo iface lo inet loopback - -iface eth0 inet static - EOF } @@ -895,7 +892,9 @@ start) ;; stop) - log_action_begin_msg "Stopping cloud-early-config (noop)" + log_action_begin_msg "Stopping cloud-early-config" + #Override old system's interface setting + setup_default; log_action_end_msg 0 ;; diff --git a/patches/systemvm/debian/config/root/redundant_router/enable_pubip.sh.templ b/patches/systemvm/debian/config/root/redundant_router/enable_pubip.sh.templ index 8be4265efb9..32604954990 100644 --- a/patches/systemvm/debian/config/root/redundant_router/enable_pubip.sh.templ +++ b/patches/systemvm/debian/config/root/redundant_router/enable_pubip.sh.templ @@ -5,8 +5,8 @@ set -e ip link|grep BROADCAST|grep -v eth0|grep -v eth1|cut -d ":" -f 2 > /tmp/iflist while read i do - ifconfig $i down - ifconfig $i up + ifdown $i + ifup $i done < /tmp/iflist ip route add default via [GATEWAY] dev eth2 && \ service dnsmasq restart diff --git a/server/src/com/cloud/cluster/ClusterManagerImpl.java b/server/src/com/cloud/cluster/ClusterManagerImpl.java index 56e9bccf9f4..4c7d4f28c1e 100755 --- a/server/src/com/cloud/cluster/ClusterManagerImpl.java +++ b/server/src/com/cloud/cluster/ClusterManagerImpl.java @@ -399,6 +399,23 @@ public class ClusterManagerImpl implements ClusterManager { s_logger.warn("Operation timed out", e); return null; } + Answer[] answers = new Answer[1]; + answers[0] = new Answer(cmd, result, null); + return _gson.toJson(answers); + } else if (cmds.length == 1 && cmds[0] instanceof PropagateResourceEventCommand) { + PropagateResourceEventCommand cmd = (PropagateResourceEventCommand) cmds[0]; + if (s_logger.isDebugEnabled()) { + s_logger.debug("Intercepting resource manager command: " + _gson.toJson(cmd)); + } + + boolean result = false; + try { + result = _resourceMgr.executeUserRequest(cmd.getHostId(), cmd.getEvent()); + } catch (Exception e) { + s_logger.warn("Exception happened while exceuting command from resource manager in other mgmt server", e); + return null; + } + Answer[] answers = new Answer[1]; answers[0] = new Answer(cmd, result, null); return _gson.toJson(answers); diff --git a/server/src/com/cloud/cluster/agentlb/ClusterBasedAgentLoadBalancerPlanner.java b/server/src/com/cloud/cluster/agentlb/ClusterBasedAgentLoadBalancerPlanner.java index 67c50b609be..9951188036b 100755 --- a/server/src/com/cloud/cluster/agentlb/ClusterBasedAgentLoadBalancerPlanner.java +++ b/server/src/com/cloud/cluster/agentlb/ClusterBasedAgentLoadBalancerPlanner.java @@ -76,6 +76,7 @@ public class ClusterBasedAgentLoadBalancerPlanner implements AgentLoadBalancerPl } sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getResource(), Op.NNULL); sc.addAnd(sc.getEntity().getManagementServerId(), Op.EQ, msId); sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up); List directHosts = sc.list(); diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index c85b3c7ca31..d044d4f3525 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1936,19 +1936,21 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian result = false; } if (result == false) { - return false; + return result; } answer = cmds.getAnswer("getDomRVersion"); if (answer != null && answer instanceof GetDomRVersionAnswer) { GetDomRVersionAnswer versionAnswer = (GetDomRVersionAnswer)answer; if (answer == null || !answer.getResult()) { - /* Try to push on because it's not a critical error */ - s_logger.warn("Unable to get the template/scripts version of router " + router.getInstanceName() + " due to: " + versionAnswer.getDetails() + ", but we would continue"); + s_logger.warn("Unable to get the template/scripts version of router " + router.getInstanceName() + " due to: " + versionAnswer.getDetails()); + result = false; } else { router.setTemplateVersion(versionAnswer.getTemplateVersion()); router.setScriptsVersion(versionAnswer.getScriptsVersion()); router = _routerDao.persist(router); } + } else { + result = false; } return result; diff --git a/server/src/com/cloud/upgrade/dao/Upgrade2214to30.java b/server/src/com/cloud/upgrade/dao/Upgrade2214to30.java index 14fab7dd83b..9a478d20088 100755 --- a/server/src/com/cloud/upgrade/dao/Upgrade2214to30.java +++ b/server/src/com/cloud/upgrade/dao/Upgrade2214to30.java @@ -22,6 +22,7 @@ import java.sql.Types; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import org.apache.log4j.Logger; @@ -29,7 +30,6 @@ import org.apache.log4j.Logger; import com.cloud.offering.NetworkOffering; import com.cloud.utils.crypt.DBEncryptionUtil; import com.cloud.utils.crypt.EncryptionSecretKeyChecker; - import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; @@ -82,8 +82,10 @@ public class Upgrade2214to30 implements DbUpgrade { updateReduntantRouters(conn); // update networks that have to switch from Shared to Isolated network offerings switchAccountSpecificNetworksToIsolated(conn); + // update networks to external network offerings if needed + String externalOfferingName = fixNetworksWithExternalDevices(conn); // create service/provider map for network offerings - createNetworkOfferingServices(conn); + createNetworkOfferingServices(conn, externalOfferingName); // create service/provider map for networks createNetworkServices(conn); //migrate user concentrated deployment planner choice to new global setting @@ -854,67 +856,97 @@ public class Upgrade2214to30 implements DbUpgrade { } } - private void createNetworkOfferingServices(Connection conn) { + private void createNetworkOfferingServices(Connection conn, String externalOfferingName) { PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = conn - .prepareStatement("select id, dns_service, gateway_service, firewall_service, lb_service, userdata_service, vpn_service, dhcp_service, unique_name from `cloud`.`network_offerings` where traffic_type='Guest'"); + .prepareStatement("select id, dns_service, gateway_service, firewall_service, lb_service, userdata_service," + + " vpn_service, dhcp_service, unique_name from `cloud`.`network_offerings` where traffic_type='Guest'"); rs = pstmt.executeQuery(); while (rs.next()) { + boolean sharedSourceNat = false; + boolean dedicatedLb = true; long id = rs.getLong(1); String uniqueName = rs.getString(9); - ArrayList services = new ArrayList(); + Map services = new HashMap(); if (rs.getLong(2) != 0) { - services.add("Dns"); + services.put("Dns", "VirtualRouter"); } if (rs.getLong(3) != 0) { - services.add("Gateway"); + if (externalOfferingName != null && uniqueName.equalsIgnoreCase(externalOfferingName)) { + services.put("Gateway", "JuniperSRX"); + } else { + services.put("Gateway", "VirtualRouter"); + } } if (rs.getLong(4) != 0) { - services.add("Firewall"); + if (externalOfferingName != null && uniqueName.equalsIgnoreCase(externalOfferingName)) { + services.put("Firewall", "JuniperSRX"); + } else { + services.put("Firewall", "VirtualRouter"); + } } if (rs.getLong(5) != 0) { - services.add("Lb"); + if (externalOfferingName != null && uniqueName.equalsIgnoreCase(externalOfferingName)) { + services.put("Lb", "F5BigIp"); + dedicatedLb = false; + } else { + services.put("Lb", "VirtualRouter"); + } } if (rs.getLong(6) != 0) { - services.add("UserData"); + services.put("UserData", "VirtualRouter"); } if (rs.getLong(7) != 0) { - services.add("Vpn"); + if (externalOfferingName == null || !uniqueName.equalsIgnoreCase(externalOfferingName)) { + services.put("Vpn", "VirtualRouter"); + } } if (rs.getLong(8) != 0) { - services.add("Dhcp"); + services.put("Dhcp", "VirtualRouter"); } if (uniqueName.equalsIgnoreCase(NetworkOffering.DefaultSharedNetworkOfferingWithSGService.toString())) { - services.add("SecurityGroup"); + services.put("SecurityGroup", "SecurityGroupProvider"); } - if (uniqueName.equals(NetworkOffering.DefaultIsolatedNetworkOfferingWithSourceNatService.toString())) { - services.add("SourceNat"); - services.add("PortForwarding"); - services.add("StaticNat"); + if (uniqueName.equals(NetworkOffering.DefaultIsolatedNetworkOfferingWithSourceNatService.toString()) || uniqueName.equalsIgnoreCase(externalOfferingName)) { + if (externalOfferingName != null && uniqueName.equalsIgnoreCase(externalOfferingName)) { + services.put("SourceNat", "JuniperSRX"); + services.put("PortForwarding", "JuniperSRX"); + services.put("StaticNat", "JuniperSRX"); + sharedSourceNat = true; + } else { + services.put("SourceNat", "VirtualRouter"); + services.put("PortForwarding", "VirtualRouter"); + services.put("StaticNat", "VirtualRouter"); + } } - for (String service : services) { - pstmt = conn.prepareStatement("INSERT INTO `cloud`.`ntwk_offering_service_map` (`network_offering_id`, `service`, `provider`, `created`) values (?,?,?, now())"); + for (String service : services.keySet()) { + pstmt = conn.prepareStatement("INSERT INTO `cloud`.`ntwk_offering_service_map` (`network_offering_id`," + + " `service`, `provider`, `created`) values (?,?,?, now())"); pstmt.setLong(1, id); pstmt.setString(2, service); - if (service.equalsIgnoreCase("SecurityGroup")) { - pstmt.setString(3, "SecurityGroupProvider"); - } else { - pstmt.setString(3, "VirtualRouter"); - } + pstmt.setString(3, services.get(service)); pstmt.executeUpdate(); } + + //update shared source nat and dedicated lb + pstmt = conn.prepareStatement("UPDATE `cloud`.`network_offerings` set shared_source_nat_service=?, dedicated_lb_service=? where id=?"); + pstmt.setBoolean(1, sharedSourceNat); + pstmt.setBoolean(2, dedicatedLb); + pstmt.setLong(3, id); + pstmt.executeUpdate(); + } } catch (SQLException e) { throw new CloudRuntimeException("Unable to create service/provider map for network offerings", e); @@ -1175,7 +1207,7 @@ public class Upgrade2214to30 implements DbUpgrade { return ; } - // get all networks that need to be updated to the redundant network offerings + // get all networks that need to be updated to the isolated network offering pstmt = conn .prepareStatement("select id, network_offering_id from `cloud`.`networks` where switch_to_isolated=1"); rs = pstmt.executeQuery(); @@ -1310,4 +1342,107 @@ public class Upgrade2214to30 implements DbUpgrade { } } } + + protected String fixNetworksWithExternalDevices(Connection conn) { + PreparedStatement pstmt = null; + ResultSet rs = null; + ResultSet rs1 = null; + + //Get zones to upgrade + List zoneIds = new ArrayList(); + try { + pstmt = conn.prepareStatement("select id from `cloud`.`data_center` where lb_provider='F5BigIp' or firewall_provider='JuniperSRX' or gateway_provider='JuniperSRX'"); + rs = pstmt.executeQuery(); + while (rs.next()) { + zoneIds.add(rs.getLong(1)); + } + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to switch networks to the new network offering", e); + } + + + String uniqueName = null; + HashMap newNetworkOfferingMap = new HashMap(); + + for (Long zoneId : zoneIds) { + try { + // Find the correct network offering + pstmt = conn + .prepareStatement("select id, network_offering_id from `cloud`.`networks` where guest_type='Virtual' and data_center_id=?"); + pstmt.setLong(1, zoneId); + rs = pstmt.executeQuery(); + pstmt = conn.prepareStatement("select count(*) from `cloud`.`network_offerings`"); + rs1 = pstmt.executeQuery(); + long ntwkOffCount = 0; + while (rs1.next()) { + ntwkOffCount = rs1.getLong(1); + } + + pstmt = conn.prepareStatement("CREATE TEMPORARY TABLE `cloud`.`network_offerings2` ENGINE=MEMORY SELECT * FROM `cloud`.`network_offerings` WHERE id=1"); + pstmt.executeUpdate(); + + + while (rs.next()) { + long networkId = rs.getLong(1); + long networkOfferingId = rs.getLong(2); + s_logger.debug("Updating network offering for the network id=" + networkId + " as it has switch_to_isolated=1"); + Long newNetworkOfferingId = null; + if (!newNetworkOfferingMap.containsKey(networkOfferingId)) { + uniqueName = "Isolated with external providers"; + // clone the record to + pstmt = conn.prepareStatement("INSERT INTO `cloud`.`network_offerings2` SELECT * FROM `cloud`.`network_offerings` WHERE id=?"); + pstmt.setLong(1, networkOfferingId); + pstmt.executeUpdate(); + + //set the new unique name + pstmt = conn.prepareStatement("UPDATE `cloud`.`network_offerings2` SET id=?, unique_name=?, name=? WHERE id=?"); + ntwkOffCount = ntwkOffCount + 1; + newNetworkOfferingId = ntwkOffCount; + pstmt.setLong(1, newNetworkOfferingId); + pstmt.setString(2, uniqueName); + pstmt.setString(3, uniqueName); + pstmt.setLong(4, networkOfferingId); + pstmt.executeUpdate(); + + pstmt = conn.prepareStatement("INSERT INTO `cloud`.`network_offerings` SELECT * from " + + "`cloud`.`network_offerings2` WHERE id=" + newNetworkOfferingId); + pstmt.executeUpdate(); + + pstmt = conn.prepareStatement("UPDATE `cloud`.`networks` SET network_offering_id=? where id=?"); + pstmt.setLong(1, newNetworkOfferingId); + pstmt.setLong(2, networkId); + pstmt.executeUpdate(); + + newNetworkOfferingMap.put(networkOfferingId, ntwkOffCount); + } else { + pstmt = conn.prepareStatement("UPDATE `cloud`.`networks` SET network_offering_id=? where id=?"); + newNetworkOfferingId = newNetworkOfferingMap.get(networkOfferingId); + pstmt.setLong(1, newNetworkOfferingId); + pstmt.setLong(2, networkId); + pstmt.executeUpdate(); + } + + s_logger.debug("Successfully updated network id=" + networkId + " with new network offering id " + newNetworkOfferingId); + } + + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to switch networks to the new network offering", e); + } finally { + try { + pstmt = conn.prepareStatement("DROP TABLE `cloud`.`network_offerings2`"); + pstmt.executeUpdate(); + if (rs != null) { + rs.close(); + } + + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + } + + return uniqueName; + } } diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java index d2f01b109d6..b2b4ce04ccc 100755 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -768,14 +768,6 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkS } - @Override - public IpAddress allocateIP(long networkId, Account ipOwner, - boolean isSystem) throws ResourceAllocationException, - InsufficientAddressCapacityException, ConcurrentOperationException { - // TODO Auto-generated method stub - return null; - } - @Override public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, boolean isSystem) @@ -880,4 +872,13 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkS // TODO Auto-generated method stub return null; } + + /* (non-Javadoc) + * @see com.cloud.network.NetworkService#allocateIP(long, com.cloud.user.Account) + */ + @Override + public IpAddress allocateIP(long networkId, Account ipOwner) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { + // TODO Auto-generated method stub + return null; + } } diff --git a/server/test/com/cloud/upgrade/AdvanceZone223To224UpgradeTest.java b/server/test/com/cloud/upgrade/AdvanceZone223To224UpgradeTest.java index 5ddb19079c4..ce47449ef0f 100644 --- a/server/test/com/cloud/upgrade/AdvanceZone223To224UpgradeTest.java +++ b/server/test/com/cloud/upgrade/AdvanceZone223To224UpgradeTest.java @@ -40,8 +40,8 @@ public class AdvanceZone223To224UpgradeTest extends TestCase { } public void test217to22Upgrade() throws SQLException { - s_logger.debug("Finding sample data from 2.2.8"); -// DbTestUtils.executeScript("PreviousDatabaseSchema/2.2.8/dave-sample.sql", false, true); + s_logger.debug("Finding sample data from 2.2.14"); +// DbTestUtils.executeScript("PreviousDatabaseSchema/2.2.14/dave-sample.sql", false, true); Connection conn; PreparedStatement pstmt; @@ -50,9 +50,9 @@ public class AdvanceZone223To224UpgradeTest extends TestCase { DatabaseUpgradeChecker checker = ComponentLocator.inject(DatabaseUpgradeChecker.class); String version = dao.getCurrentVersion(); - assert version.equals("2.2.8") : "Version returned is not 2.2.8 but " + version; + assert version.equals("2.2.14") : "Version returned is not 2.2.14 but " + version; - checker.upgrade("2.2.8", "2.2.12"); + checker.upgrade("2.2.14", "3.0.3"); } } diff --git a/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java b/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java index ea4950ba2b0..5a65a6d13f9 100755 --- a/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java +++ b/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java @@ -217,4 +217,22 @@ public class MockVirtualMachineManagerImpl implements VirtualMachineManager { return null; } + /* (non-Javadoc) + * @see com.cloud.vm.VirtualMachineManager#checkIfCanUpgrade(com.cloud.vm.VirtualMachine, long) + */ + @Override + public void checkIfCanUpgrade(VirtualMachine vmInstance, long newServiceOfferingId) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see com.cloud.vm.VirtualMachineManager#upgradeVmDb(long, long) + */ + @Override + public boolean upgradeVmDb(long vmId, long serviceOfferingId) { + // TODO Auto-generated method stub + return false; + } + } diff --git a/setup/db/db/schema-302to303.sql b/setup/db/db/schema-302to303.sql index ffb0d96da7b..30f53b2fb1e 100755 --- a/setup/db/db/schema-302to303.sql +++ b/setup/db/db/schema-302to303.sql @@ -168,3 +168,5 @@ CREATE TABLE `cloud`.`port_profile` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; DELETE FROM `cloud`.`storage_pool_host_ref` WHERE pool_id IN (SELECT id FROM storage_pool WHERE removed IS NOT NULL); + +ALTER TABLE `cloud`.`service_offering` MODIFY `nw_rate` smallint(5) unsigned DEFAULT '200' COMMENT 'network rate throttle mbits/s'; diff --git a/test/integration/component/test_accounts.py b/test/integration/component/test_accounts.py index c8a7a234bc4..19f6914229f 100644 --- a/test/integration/component/test_accounts.py +++ b/test/integration/component/test_accounts.py @@ -19,7 +19,7 @@ from marvin.cloudstackAPI import * from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient import datetime diff --git a/test/integration/component/test_blocker_bugs.py b/test/integration/component/test_blocker_bugs.py index 5da10b70b75..4155a41aa13 100644 --- a/test/integration/component/test_blocker_bugs.py +++ b/test/integration/component/test_blocker_bugs.py @@ -21,7 +21,7 @@ from integration.lib.common import * #Import Local Modules from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient class Services: """Test Services diff --git a/test/integration/component/test_egress_rules.py b/test/integration/component/test_egress_rules.py index 751a595bd77..aa301dad3cb 100644 --- a/test/integration/component/test_egress_rules.py +++ b/test/integration/component/test_egress_rules.py @@ -18,7 +18,7 @@ import marvin from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * diff --git a/test/integration/component/test_high_availability.py b/test/integration/component/test_high_availability.py index 9d1ac019f4f..10281615cc3 100644 --- a/test/integration/component/test_high_availability.py +++ b/test/integration/component/test_high_availability.py @@ -21,7 +21,7 @@ from marvin.cloudstackAPI import * from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient import datetime @@ -168,7 +168,7 @@ class TestHighAvailability(cloudstackTestCase): except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return - @unittest.skip("skipped") + def test_01_host_maintenance_mode(self): """Test host maintenance mode """ diff --git a/test/integration/component/test_netscaler_configs.py b/test/integration/component/test_netscaler_configs.py new file mode 100644 index 00000000000..a76a19b8b2e --- /dev/null +++ b/test/integration/component/test_netscaler_configs.py @@ -0,0 +1,2965 @@ +# -*- encoding: utf-8 -*- +# Copyright 2012 Citrix Systems, Inc. Licensed under the +# Apache License, Version 2.0 (the "License"); you may not use this +# file except in compliance with the License. Citrix Systems, Inc. +# reserves all rights not expressly granted by the License. +# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Automatically generated by addcopyright.py at 04/03/2012 + +""" P1 tests for netscaler configurations +""" +#Import Local Modules +import marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from integration.lib.utils import * +from integration.lib.base import * +from integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test netscaler Services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "virtual_machine": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "netscaler": { + "ipaddress": '192.168.100.213', + "username": 'nsroot', + "password": 'nsroot', + "networkdevicetype": 'NetscalerVPXLoadBalancer', + "publicinterface": '1/1', + "privateinterface": '0/1', + "numretries": 2, + "lbdevicededicated": False, + "lbdevicecapacity": 50, + "port": 22, + }, + "network_offering_dedicated": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "specifyVlan": False, + "specifyIpRanges": False, + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + "servicecapabilitylist": { + "SourceNat": { + "SupportedSourceNatTypes": "peraccount" + }, + "lb": { + "SupportedLbIsolation": "dedicated" + }, + }, + }, + "network_offering": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "network": { + "name": "Netscaler", + "displaytext": "Netscaler", + }, + "lbrule": { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 22, + "openfirewall": False, + }, + "ostypeid": '946b031b-0e10-4f4a-a3fc-d212ae2ea07f', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode":'advanced' + } + + +class TestAddNetScaler(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestAddNetScaler, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls._cleanup = [] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_add_netscaler_device(self): + """Test add netscaler device + """ + + # Validate the following + # 1. Add Netscaler device into a Zone by providing valid log in + # credentials , public , private interface and enabling Load + # Balancing feature. + # 2. Netscaler should be configured successfully. + + physical_networks = PhysicalNetwork.list( + self.apiclient, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(physical_networks, list), + True, + "There should be atleast one physical network for advanced zone" + ) + physical_network = physical_networks[0] + self.debug("Adding netscaler device: %s" % + self.services["netscaler"]["ipaddress"]) + netscaler = NetScaler.add( + self.apiclient, + self.services["netscaler"], + physicalnetworkid=physical_network.id + ) + self.cleanup.append(netscaler) + self.debug("Checking if Netscaler network service provider is enabled?") + + nw_service_providers = NetworkServiceProvider.list( + self.apiclient, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + self.assertEqual( + isinstance(nw_service_providers, list), + True, + "Network service providers list should not be empty" + ) + netscaler_provider = nw_service_providers[0] + if netscaler_provider.state != 'Enabled': + self.debug("Netscaler provider is not enabled. Enabling it..") + response = NetworkServiceProvider.update( + self.apiclient, + id=netscaler_provider.id, + state='Enabled' + ) + self.assertEqual( + response.state, + "Enabled", + "Network service provider should be in enabled state" + ) + else: + self.debug("Netscaler service provider is already enabled.") + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + self.assertEqual( + ns.physicalnetworkid, + physical_network.id, + "Physical network id should match with the network in which device is configured" + ) + return + + +class TestInvalidParametersNetscaler(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestInvalidParametersNetscaler, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls._cleanup = [] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_invalid_cred(self): + """Test add netscaler device with invalid credential + """ + + # Validate the following + # 1. Add Netscaler device into a Zone by providing invalid log in + # credentials , but valid public, private interface + # 2. Netscaler API should throw error + + physical_networks = PhysicalNetwork.list( + self.apiclient, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(physical_networks, list), + True, + "There should be atleast one physical network for advanced zone" + ) + physical_network = physical_networks[0] + + self.debug("Checking if Netscaler network service provider is enabled?") + + nw_service_providers = NetworkServiceProvider.list( + self.apiclient, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + self.assertEqual( + isinstance(nw_service_providers, list), + True, + "Network service providers list should not be empty" + ) + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + self.debug("Netscaler provider is not enabled. Enabling it..") + response = NetworkServiceProvider.update( + self.apiclient, + id=netscaler_provider.id, + state='Enabled' + ) + self.assertEqual( + response.state, + "Enabled", + "Network service provider should be in enabled state" + ) + else: + self.debug("NetScaler service provider is already enabled.") + + self.debug("Passing invalid credential for NetScaler") + self.services["netscaler"]["username"] = random_gen() + self.services["netscaler"]["password"] = random_gen() + self.debug("Adding netscaler device: %s" % + self.services["netscaler"]["ipaddress"]) + + self.debug("Username: %s, password: %s" % ( + self.services["netscaler"]["username"], + self.services["netscaler"]["password"] + )) + + with self.assertRaises(Exception): + NetScaler.add( + self.apiclient, + self.services["netscaler"], + physicalnetworkid=physical_network.id + ) + return + + def test_invalid_public_interface(self): + """Test add netscaler device with invalid public interface + """ + + # Validate the following + # 1. Add Netscaler device into a Zone by providing valid log in + # credentials , private interface and invalid public interface + # 2. Netscaler API should throw error + + physical_networks = PhysicalNetwork.list( + self.apiclient, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(physical_networks, list), + True, + "There should be atleast one physical network for advanced zone" + ) + physical_network = physical_networks[0] + + self.debug("Checking if Netscaler network service provider is enabled?") + + nw_service_providers = NetworkServiceProvider.list( + self.apiclient, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + self.assertEqual( + isinstance(nw_service_providers, list), + True, + "Network service providers list should not be empty" + ) + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + self.debug("Netscaler provider is not enabled. Enabling it..") + response = NetworkServiceProvider.update( + self.apiclient, + id=netscaler_provider.id, + state='Enabled' + ) + self.assertEqual( + response.state, + "Enabled", + "Network service provider should be in enabled state" + ) + else: + self.debug("NetScaler service provider is already enabled.") + + self.debug("Passing invalid public interface for NetScaler") + self.services["netscaler"]["publicinterface"] = random_gen() + + self.debug("Adding netscaler device: %s" % + self.services["netscaler"]["ipaddress"]) + + self.debug("Public interface: %s" % + self.services["netscaler"]["publicinterface"]) + + with self.assertRaises(Exception): + NetScaler.add( + self.apiclient, + self.services["netscaler"], + physicalnetworkid=physical_network.id + ) + return + + def test_invalid_private_interface(self): + """Test add netscaler device with invalid private interface + """ + + # Validate the following + # 1. Add Netscaler device into a Zone by providing valid log in + # credentials , public interface and invalid private interface + # 2. Netscaler API should throw error + + physical_networks = PhysicalNetwork.list( + self.apiclient, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(physical_networks, list), + True, + "There should be atleast one physical network for advanced zone" + ) + physical_network = physical_networks[0] + + self.debug("Checking if Netscaler network service provider is enabled?") + + nw_service_providers = NetworkServiceProvider.list( + self.apiclient, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + self.assertEqual( + isinstance(nw_service_providers, list), + True, + "Network service providers list should not be empty" + ) + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + self.debug("Netscaler provider is not enabled. Enabling it..") + response = NetworkServiceProvider.update( + self.apiclient, + id=netscaler_provider.id, + state='Enabled' + ) + self.assertEqual( + response.state, + "Enabled", + "Network service provider should be in enabled state" + ) + else: + self.debug("NetScaler service provider is already enabled.") + + self.debug("Passing invalid private interface for NetScaler") + self.services["netscaler"]["privateinterface"] = random_gen() + + self.debug("Adding netscaler device: %s" % + self.services["netscaler"]["ipaddress"]) + + self.debug("Private interface: %s" % + self.services["netscaler"]["privateinterface"]) + + with self.assertRaises(Exception): + NetScaler.add( + self.apiclient, + self.services["netscaler"], + physicalnetworkid=physical_network.id + ) + return + +@unittest.skip("Issue- Unable to validate user credentials while creating nw offering") +class TestNetScalerDedicated(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNetScalerDedicated, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + + cls.services["netscaler"]["lbdevicededicated"] = True + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering_dedicated"], + conservemode=False, + state="Creating", + status="Creating", + allocationstate="Creating", + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_netscaler_dedicated_mode(self): + """Test netscaler device in dedicated mode + """ + + # Validate the following + # 1. Add Netscaler device in dedicated mode. + # 2. Netscaler should be configured successfully.It should be able to + # service only 1 account. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + True, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + with self.assertRaises(Exception): + Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + return + + +class TestNetScalerShared(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNetScalerShared, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_netscaler_dedicated_mode(self): + """Test netscaler device in dedicated mode + """ + + # Validate the following + # 1. Add Netscaler device in dedicated mode. + # 2. Netscaler should be configured successfully.It should be able to + # service only 1 account. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_2.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_2.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_2.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + return + + +class TestNetScalerCustomCapacity(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNetScalerCustomCapacity, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + cls.services["netscaler"]["lbdevicecapacity"] = 2 + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_3 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2, self.account_3] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_netscaler_dedicated_mode(self): + """Test netscaler device in dedicated mode + """ + + # Validate the following + # 1. Add Netscaler device in dedicated mode. + # 2. Netscaler should be configured successfully.It should be able to + # service only 1 account. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_2.id) + + self.debug("Deploying VM in account: %s" % self.account_2.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_2.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_2.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_3 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_3.id) + + self.debug("Deploying VM in account: %s" % self.account_3.account.name) + with self.assertRaises(Exception): + # Spawn an instance in that network + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_3.id)] + ) + return + + +class TestNetScalerNoCapacity(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNetScalerNoCapacity, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_3 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2, self.account_3] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_netscaler_dedicated_mode(self): + """Test netscaler device in dedicated mode + """ + + # Validate the following + # 1. Add Netscaler device in dedicated mode. + # 2. Netscaler should be configured successfully.It should be able to + # service only 1 account. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_2.id) + + self.debug("Deploying VM in account: %s" % self.account_2.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_2.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_2.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_3 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_3.id) + + self.debug("Deploying VM in account: %s" % self.account_3.account.name) + with self.assertRaises(Exception): + # Spawn an instance in that network + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_3.id)] + ) + return + + +class TestGuestNetworkWithNetScaler(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestGuestNetworkWithNetScaler, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_guest_network(self): + """Implementing Guest Network when first VM gets deployed using the network having Netscaler as LB + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3.Create a new account/user. + # 4. Deploy the first VM using a network from the above created + # Network offering. + # In Netscaler: + # 1. Private interface of Netscaler device will be configured to make + # it part of the virtual guest network by binding the interface to + # the VLAN and subnet allocated for the virtual guest network + # 2. Private interface should be associated with a self-ip (second IP + # in the subnet) from the guest subnet. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network_1.id, + listall=True + ) + nw = network_list[0] + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource "), + 1, + "Netscaler should have vlan configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_02_guest_network_multiple(self): + """Implementing Guest Network when multiple VMs gets deployed using the network having Netscaler as LB + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3.Create a new account/user. + # 4. Deploy the first VM using a network from the above created + # Network offering. + # In Netscaler: + # 1. Private interface of Netscaler device will be configured to make + # it part of the virtual guest network by binding the interface to + # the VLAN and subnet allocated for the virtual guest network + # 2. Private interface should be associated with a self-ip (second IP + # in the subnet) from the guest subnet. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_2.id) + + self.debug("Deploying VM in account: %s" % self.account_2.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_2.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_2.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network_1.id, + listall=True + ) + nw = network_list[0] + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource "), + 1, + "Netscaler should have vlan configured for the network" + ) + + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network_2.id, + listall=True + ) + nw = network_list[0] + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should have vlan configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_03_delete_account(self): + """Delete an account that has LB rules + """ + + # Validate the following + # 1. Acquire an ipaddress. Create multiple Lb rules on this ip address + # 2. Delete this account that has LB rules + # In Netscaler: + # 1. Private interface on the netscaler LB device will be unbound to + # vlan and subnet + # 2. All the service instance and the servers that are part of this + # vlan, that were created on the Netscaler device as part of + # applying LB rules will be destroyed. + # 3. Any lb virtual server that is created using this public IP + # allocated for the account will be destroyed + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Assigning public IP for the account: %s" % + self.account_1.account.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account_1.account.name, + zoneid=self.zone.id, + domainid=self.account_1.account.domainid, + networkid=self.network.id + ) + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + public_ip.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account_1.account.name, + networkid=self.network.id + ) + self.debug("Created the load balancing rule for public IP: %s" % + public_ip.ipaddress.ipaddress) + self.debug("Assigning VMs to LB rule") + lb_rule.assign(self.apiclient, [virtual_machine]) + + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network.id, + listall=True + ) + nw = network_list[0] + + self.debug("Deleting account: %s" % self.account_1.account.name) + # This is a hack. Delete first account from cleanup list + self.cleanup.pop(0).delete(self.apiclient) + self.debug("Account: %s is deleted!" % self.account_1.account.name) + + self.debug("Waiting for network.gc.interval & network.gc.wait..") + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should have vlan configured for the network" + ) + + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should have vlan configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +class TestGuestNetworkShutDown(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestGuestNetworkShutDown, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + # Creating network using the network offering created + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn few instances in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls.lb_rule = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + ipaddressid=cls.public_ip.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network.id + ) + cls.lb_rule.assign(cls.api_client, [cls.vm_1, cls.vm_2]) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_stop_all_vms(self): + """Test Stopping all the Vms for any account that has LB rules. + """ + + # Validate the following + # 1. Acquire IP address and create a load balancer rule + # 2. Stop all VMs in the account that has LB rules + # 3. This will result in the network being shutdown. As part of this, + # this account and the all the Lb rules for this account should get + # removed from the Netscaler + + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network.id, + listall=True + ) + nw = network_list[0] + self.debug("Network vlan used is: %s" % nw.vlan) + + self.debug( + "Stopping all the VM instances for the account: %s" % + self.account.account.name) + + self.vm_1.stop(self.apiclient) + self.vm_2.stop(self.apiclient) + + self.debug("Sleep for network.gc.interval + network.gc.wait") + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep((int(interval[0].value) + int(wait[0].value))*2) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should not have vlan configured for the network" + ) + + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + self.lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should not have vserver configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_02_start_one_vm(self): + """Test LB rules on Netscaler after starting one Vm in account + """ + + # Validate the following + # 1. Acquire IP address and create a load balancer rule + # 2. Stop all VMs in the account that has LB rules + # 3. This will result in the network being shutdown. As part of this, + # this account and the all the Lb rules for this account should get + # removed from the Netscaler + # 3. Start one of the VMs. LB rules should get reconfigured on + # Netscaler + + self.debug( + "starting one VM instances for the account: %s" % + self.account.account.name) + self.vm_1.start(self.apiclient) + + vms = VirtualMachine.list( + self.apiclient, + id=self.vm_1.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid list" + ) + + for vm in vms: + self.assertEqual( + vm.state, + "Running", + "VM instance should be Up and running after start" + ) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network.id, + listall=True + ) + nw = network_list[0] + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource "), + 1, + "Netscaler should have vlan configured for the network" + ) + + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + self.lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should have vlan configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_03_network_restart_without_cleanup(self): + """Test LB rules on Netscaler after network restart without cleanup + """ + + # Validate the following + # 1. Acquire IP address and create a load balancer rule + # 2. Restart network->without cleanup option enabled + # 3. All existing Lb rules get added again to the netscaler. All the + # existing LB rules should continue to work. + + self.debug("Restarting the network: %s" % self.network.id) + self.network.restart(self.apiclient, cleanup=False) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network.id, + listall=True + ) + nw = network_list[0] + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource "), + 1, + "Netscaler should have vlan configured for the network" + ) + + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + self.lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should have vlan configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_04_network_restart_with_cleanup(self): + """Test LB rules on Netscaler after network restart with cleanup + """ + + # Validate the following + # 1. Acquire IP address and create a load balancer rule + # 2. Restart network->with cleanup option enabled + # 3. All existing Lb rules get deleted and reconfigured again to the + # netscaler. All the existing LB rules should continue to work. + + self.debug("Restarting the network: %s" % self.network.id) + self.network.restart(self.apiclient, cleanup=True) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network.id, + listall=True + ) + nw = network_list[0] + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource "), + 1, + "Netscaler should have vlan configured for the network" + ) + + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + self.lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should have vlan configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +class TestServiceProvider(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestServiceProvider, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + cls.netscaler_provider = nw_service_providers[0] + + if cls.netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=cls.netscaler_provider.id, + state='Enabled' + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Enable the service provider + NetworkServiceProvider.update( + cls.api_client, + id=cls.netscaler_provider.id, + state='Enabled' + ) + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_create_nw_off_disabled(self): + """Test create network with network offering disabled + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering. Do not enable the network offering + # 3. Try to create a network with this network offering. + # 4. Network creation should fail + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + with self.assertRaises(Exception): + Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + return + + def test_02_create_nw_sp_disabled(self): + """Test create network when service provider is disabled + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Disable the service provider. Create a Network offering. + # 3. Try to create a network. Network creation should fail + + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + + # Disable the service provider + NetworkServiceProvider.update( + self.apiclient, + id=self.netscaler_provider.id, + state='Disabled' + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + with self.assertRaises(Exception): + Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + return + + def test_03_create_lb_sp_disabled(self): + """Test create LB rules when service provider is disabled + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering. Create instances and acquire public Ip + # 3. Disabled service provider and again try to create LB rules + # 4.Deploy VM should fail + + # Enable the service provider + NetworkServiceProvider.update( + self.apiclient, + id=self.netscaler_provider.id, + state='Enabled' + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Acquiring a public IP for Network: %s" % self.network.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + public_ip.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.debug("Created the load balancing rule for public IP: %s" % + public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + virtual_machine.name, + lb_rule.name + )) + self.debug("Disabling Netscaler service provider") + + # Disable the service provider + NetworkServiceProvider.update( + self.apiclient, + id=self.netscaler_provider.id, + state='Disabled' + ) + self.debug("Deploying VM in the network: %s" % self.network.id) + with self.assertRaises(Exception): + VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + return + + +class TestDeleteNetscaler(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestDeleteNetscaler, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_delete_netscaler_with_lb(self): + """Test delete Netscaler when active LB rules are present + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3.Create a new account/user. + # 4. Deploy the first VM using a network from the above created + # Network offering. + # 5. Attempt to delete Netscaler load balancer from zone. + # Deletion should NOT be allowed. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Attempt to delete netscaler load balancer device") + with self.assertRaises(Exception): + self.netscaler.delete(self.apiclient) + self.debug("Attempt to delete Netscaler device failed!") + return diff --git a/test/integration/component/test_netscaler_lb.py b/test/integration/component/test_netscaler_lb.py new file mode 100644 index 00000000000..6b1e517df98 --- /dev/null +++ b/test/integration/component/test_netscaler_lb.py @@ -0,0 +1,2924 @@ +# -*- encoding: utf-8 -*- +# Copyright 2012 Citrix Systems, Inc. Licensed under the +# Apache License, Version 2.0 (the "License"); you may not use this +# file except in compliance with the License. Citrix Systems, Inc. +# reserves all rights not expressly granted by the License. +# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Automatically generated by addcopyright.py at 04/03/2012 + +""" P1 tests for netscaler load balancing +""" +#Import Local Modules +import marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from integration.lib.utils import * +from integration.lib.base import * +from integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test netscaler services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "virtual_machine": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "netscaler": { + "ipaddress": '10.147.40.100', + "username": 'nsroot', + "password": 'nsroot', + "networkdevicetype": 'NetscalerVPXLoadBalancer', + "publicinterface": '1/1', + "privateinterface": '1/1', + "numretries": 2, + "lbdevicededicated": False, + "lbdevicecapacity": 50, + "port": 22, + }, + "network_offering_dedicated": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "specifyVlan": False, + "specifyIpRanges": False, + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + "servicecapabilitylist": { + "SourceNat": { + "SupportedSourceNatTypes": "peraccount" + }, + "lb": { + "SupportedLbIsolation": "dedicated" + }, + }, + }, + "network_offering": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "network": { + "name": "Netscaler", + "displaytext": "Netscaler", + }, + "lbrule": { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 22, + "openfirewall": False, + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "protocol": "TCP" + }, + "ostypeid": '2b58909b-7d9e-45d9-80d8-e58d0bbcbf07', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode":'advanced' + } + + +class TestLbSourceNat(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbSourceNat, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_add_lb_on_source_nat(self): + """Test Create LB rule for sourceNat IP address + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Create LB rule for the sourceNat IP address. User should NOT be + # allowed to create an LB rule on source NAT + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + src_nat_list = PublicIPAddress.list( + self.apiclient, + associatednetworkid=self.network.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True, + issourcenat=True, + ) + self.assertEqual( + isinstance(src_nat_list, list), + True, + "List Public IP should return a valid source NAT" + ) + self.assertNotEqual( + len(src_nat_list), + 0, + "Length of response from listPublicIp should not be 0" + ) + + src_nat = src_nat_list[0] + + self.debug("Trying to create LB rule on source NAT IP: %s" % + src_nat.ipaddress) + # Create Load Balancer rule with source NAT + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=src_nat.id, + accountid=self.account.account.name + ) + return + + +class TestLbOnIpWithPf(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbOnIpWithPf, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_lb_on_ip_with_pf(self): + """Test Create LB rule for sourceNat IP address + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Create LB rule on Ip with PF rule. User should NOT be + # allowed to create an LB rule on Ip with PF + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Associating public IP for network: %s" % self.network.id) + ip_with_nat_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + + self.debug("Associated %s with network %s" % ( + ip_with_nat_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating PF rule for IP address: %s" % + ip_with_nat_rule.ipaddress.ipaddress) + NATRule.create( + self.apiclient, + virtual_machine_1, + self.services["natrule"], + ipaddressid=ip_with_nat_rule.ipaddress.id + ) + + self.debug("Trying to create LB rule on IP with NAT: %s" % + ip_with_nat_rule.ipaddress.ipaddress) + + # Create Load Balancer rule on IP already having NAT rule + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_nat_rule.ipaddress.id, + accountid=self.account.account.name + ) + return + + +class TestPfOnIpWithLb(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestPfOnIpWithLb, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_pf_on_ip_with_lb(self): + """Test Create a port forwarding rule on an Ip address that already has a LB rule. + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Create PF rule on Ip with LB rule. User should NOT be + # allowed to create an LB rule on Ip with LB + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Associating public IP for network: %s" % self.network.id) + + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating LB rule for IP address: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + with self.assertRaises(Exception): + NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id + ) + return + + +class TestLbOnNonSourceNat(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbOnNonSourceNat, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=False + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_lb_on_non_source_nat(self): + """Test Create LB rule for non-sourceNat IP address + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create LB rule on it. LB rule should be + # created successfully + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Associating public IP for network: %s" % self.network.id) + + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating LB rule for IP address: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + return + + +class TestAddMultipleVmsLb(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestAddMultipleVmsLb, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_add_multiple_vms_lb(self): + """Test Add multiple Vms to an existing LB rule. + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create LB rule on it. Add multiple VMs to + # this rule. LB rule should be + # In Netscaler: For every Vm added to the LB rule: + # 1. A server and service instance is created using guest VM’s IP and + # port number on the Netscaler LB device, + # 2. This service is bound to lb virtual server corresponding to lb + # rule. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Associating public IP for network: %s" % self.network.id) + + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating LB rule for IP address: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Assigning virtual machines to LB rule") + lb_rule.assign(self.apiclient, [virtual_machine_1, virtual_machine_2]) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + 22, + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + self.debug("command: show server") + res = ssh_client.execute("show server") + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(virtual_machine_1.ipaddress), + 2, + "Server must be configured for virtual machines" + ) + self.assertEqual( + result.count(virtual_machine_2.ipaddress), + 2, + "Server must be configured for virtual machines" + ) + + self.debug("Command:show service") + res = ssh_client.execute("show service") + + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(virtual_machine_1.ipaddress), + 3, + "Service must be configured for virtual machines" + ) + self.assertEqual( + result.count(virtual_machine_2.ipaddress), + 3, + "Service must be configured for virtual machines" + ) + self.debug("Command:show lb vserver") + res = ssh_client.execute("show lb vserver") + + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(ip_with_lb_rule.ipaddress.ipaddress), + 2, + "virtual server must be configured for public IP address" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +class TestMultipleLbRules(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestMultipleLbRules, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_multiple_lb_publicip(self): + """Test Create multiple LB rules using different public Ips acquired + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy few more VMs. + # 3. Acquire an Ipaddress and create an LB rule for multiple Vms. + # Repeat step2 for few times Requests to all these LB rules should + # be serviced correctly. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug( + "Associating first public IP for network: %s" % + self.network.id) + + public_ip_1 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_1.ipaddress.ipaddress, + self.network.id + )) + + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + public_ip_1.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip_1.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s, %s to the LB rule %s" % ( + virtual_machine_1.name, + virtual_machine_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine_1, virtual_machine_2]) + + self.debug( + "Associating second public IP for network: %s" % + self.network.id) + + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + self.network.id + )) + + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + public_ip_2.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip_2.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + public_ip_2.ipaddress.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s, %s to the LB rule %s" % ( + virtual_machine_1.name, + virtual_machine_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine_1, virtual_machine_2]) + + try: + self.debug( + "Verifying VMs are accessible with different public Ips") + hostnames = [] + ssh = virtual_machine_1.get_ssh_client( + ipaddress=public_ip_1.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result[0]) + self.assertIn( + res, + [virtual_machine_1.name, virtual_machine_2.name], + "The hostname should match with atleast one of instance name" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + public_ip_1.ipaddress.ipaddress, + e)) + try: + ssh = virtual_machine_1.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + res = str(result[0]) + self.assertIn( + res, + [virtual_machine_1.name, virtual_machine_2.name], + "The hostname should match with atleast one of instance name" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + public_ip_2.ipaddress.ipaddress, + e)) + return + + + +class TestMultipleLbRulesSameIp(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestMultipleLbRulesSameIp, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_multiple_lb_same_publicip(self): + """Test Create multiple LB rules using same public Ips on diff ports + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy few more VMs. + # 3. Acquire an Ipaddress and create an LB rule for multiple Vms. + # Create another Lb rule on the same Ipaddress pointing to + # different public port. Requests to all these LB rules should be + # serviced correctly. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug( + "Associating first public IP for network: %s" % + self.network.id) + + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + self.network.id + )) + + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + lb_rule_1 = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + public_ip.ipaddress.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule_1.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s, %s to the LB rule %s" % ( + virtual_machine_1.name, + virtual_machine_2.name, + lb_rule_1.name + )) + lb_rule_1.assign(self.apiclient, [ + virtual_machine_1, + virtual_machine_2 + ]) + self.debug( + "Trying to create LB rule on IP: %s with on same ports" % + public_ip.ipaddress.ipaddress) + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.debug("Create LB rule on same port failed!") + self.debug("Creating LB rule on IP: %s & public port: %s" % ( + public_ip.ipaddress.ipaddress, + str(2222))) + + self.services["lbrule"]["alg"] = 'roundrobin' + self.services["lbrule"]["publicport"] = 2222 + self.services["lbrule"]["name"] = 'SSH2' + lb_rule_2 = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule_2.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s, %s to the LB rule %s" % ( + virtual_machine_1.name, + virtual_machine_2.name, + lb_rule_2.name + )) + lb_rule_2.assign(self.apiclient, [ + virtual_machine_1, + virtual_machine_2 + ]) + + try: + self.debug("Verifying VMs are accessible on all LB rules") + hostnames = [] + ssh = virtual_machine_1.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result[0]) + self.assertIn( + res, + [virtual_machine_1.name, virtual_machine_2.name], + "The hostname should match with atleast one of instance name" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + public_ip.ipaddress.ipaddress, + e)) + try: + ssh = virtual_machine_1.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + res = str(result[0]) + self.assertIn( + res, + [virtual_machine_1.name, virtual_machine_2.name], + "The hostname should match with atleast one of instance name" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + public_ip.ipaddress.ipaddress, + e)) + return + + +class TestLoadBalancingRule(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLoadBalancingRule, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + # Creating network using the network offering created + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls.lb_rule = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + ipaddressid=cls.public_ip.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_edit_name_lb_rule(self): + """Test edit name of LB rule + """ + + # Validate the following + # 1. Create an Lb rule for couple of Vms . + # 2. Edit the name of the existing LB rule. When all the existing + # Lbrules are listed , we should see the edited name. + + self.debug("Assigning VMs to LB rule: %s" % self.lb_rule.name) + self.lb_rule.assign(self.apiclient, [self.virtual_machine]) + + self.debug("Editing name of the LB rule: %s" % self.lb_rule.name) + new_name = random_gen() + self.lb_rule.update(self.apiclient, name=new_name) + + self.debug("Verifing the name change in list Lb rules call") + lb_rules = LoadBalancerRule.list(self.apiclient, id=self.lb_rule.id) + + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB call should return a valid list" + ) + lb = lb_rules[0] + self.assertEqual( + lb.name, + new_name, + "LB name should be updated with the new name" + ) + return + + def test_02_edit_lb_ports(self): + """Test edit public port of LB rule + """ + + # Validate the following + # 1. Create an Lb rule for couple of Vms . + # 2. Edit the public/private of the existing LB rule. When all the + # existing Lbrules are listed, this should not be allowed. + + self.debug("Editing public port of the LB rule: %s" % self.lb_rule.name) + port = 8888 + with self.assertRaises(Exception): + self.lb_rule.update(self.apiclient, publicport=port) + + self.debug("Editing private port of the LB rule: %s" % self.lb_rule.name) + with self.assertRaises(Exception): + self.lb_rule.update(self.apiclient, privateport=port) + + return + + def test_03_delete_lb_rule(self): + """Test delete LB rule + """ + + # Validate the following + # 1. Delete existing load balancing rule + # 2. In netscaler service and port corresponding to LB rule should get + # deleted. Any request to IP should error out. + + self.debug("Deleting existing load balancing rule") + self.lb_rule.delete(self.apiclient) + + self.debug("SSH into Netscaler to verify other resources are deleted") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + self.lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Virtual server should get deleted after removing LB rule" + ) + + cmd = "show ip" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(self.public_ip.ipaddress.ipaddress), + 0, + "Virtual server should get deleted after removing LB rule" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + +@unittest.skip("Questions - How to verify after changing public/private ports?") +class TestDeleteCreateLBRule(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestDeleteCreateLBRule, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + # Creating network using the network offering created + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_create_with_same_public_port(self): + """Test create LB rule with same public port after deleting rule""" + + # Validate the following + # 1. Delete existing rule and create exactly same rule with different + # public port + # 2. Requests should be served correctly + + self.debug("Delete the existing LB rule: %s" % self.lb_rule.name) + self.lb_rule.delete(self.apiclient) + self.debug("LB rule deleted") + + self.debug("Create a new LB rule with different public port") + self.services["lbrule"]["publicport"] = 23 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + +class TestVmWithLb(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVmWithLb, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + # Creating network using the network offering created + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip_1 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls.lb_rule_1 = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + ipaddressid=cls.public_ip_1.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network.id + ) + cls.public_ip_2 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls.lb_rule_2 = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + ipaddressid=cls.public_ip_2.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_delete_public_ip(self): + """Test delete one public Ip with LB rules""" + + # Validate the following + # 1. Associate 2 public Ips and create load balancing rules in it + # 2. Delete one of the public Ip + # 3. All the LB rules should be removed from that public Ip + # 4. In netscaler, make sure that all LB rules associated with that + # public Ip should get removed. + # 5. All servers and services service to that public Ip get deleted + + self.debug("Deleting public IP: %s from network: %s" % ( + self.public_ip_2.ipaddress.ipaddress, + self.network.name + )) + self.public_ip_2.delete(self.apiclient) + self.debug( + "Public Ip: %s is deleted!" % + self.public_ip_2.ipaddress.ipaddress) + lb_rules = LoadBalancerRule.list( + self.apiclient, + publicipid=self.public_ip_2.ipaddress.id, + listall=True, + ) + self.assertEqual( + lb_rules, + None, + "LB rules associated with the public Ip should get deleted" + ) + self.debug("SSH into Netscaler to verify other resources are deleted") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip_2.ipaddress.ipaddress, + self.lb_rule_2.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Virtual server should get deleted after removing LB rule" + ) + + cmd = "show ip" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(self.public_ip_2.ipaddress.ipaddress), + 0, + "Virtual server should get deleted after removing LB rule" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_02_stop_user_vm(self): + """Test stop user VM with LB""" + + # Validate the following + # 1. Create 2 instances and add these two for load balancing + # 2. Stop one of the user VM + # 3. Test whether the request are not sent to stopped user VM + # 4. In netscaler, LB rules for this VM still remain configured.But + # it will be marked as being down + + self.debug("Adding instances: %s, %s to LB rule: %s" % ( + self.vm_1.name, + self.vm_2.name, + self.lb_rule_1.name)) + self.lb_rule_1.assign(self.apiclient, [self.vm_1, self.vm_2]) + self.debug("Assigned instances: %s, %s to LB rule: %s" % ( + self.vm_1.name, + self.vm_2.name, + self.lb_rule_1.name)) + self.debug("Stopping VM instance: %s" % self.vm_2.name) + self.vm_2.stop(self.apiclient) + self.debug("Stopped VM: %s" % self.vm_2.name) + + try: + self.debug( + "Verifying request served by only running instances") + hostnames = [] + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertEqual( + hostnames[0], + hostnames[1], + "Hostnames must be same as another VM is stopped" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip_1.ipaddress.ipaddress, + e)) + self.debug("SSH into Netscaler to rules still persist") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + + cmd = "show server" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertNotEqual( + result.count(self.vm_2.ipaddress), + 0, + "The server should be present in netscaler after VM stop" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_03_start_user_vm(self): + """Test start user VM with LB""" + + # Validate the following + # 1. Create 2 instances and add these two for load balancing + # 2. Stop one of the user VM + # 3. Test whether the request are not sent to stopped user VM + # 4. In netscaler, LB rules for this VM still remain configured.But + # it will be marked as being down + + self.debug("Starting VM instance: %s" % self.vm_2.name) + self.vm_2.start(self.apiclient) + self.debug("Starting VM: %s" % self.vm_2.name) + + try: + self.debug( + "Verifying request served by only running instances") + hostnames = [] + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_2 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertNotEqual( + hostnames[0], + hostnames[1], + "Both request should be served by different instances" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip_1.ipaddress.ipaddress, + e)) + self.debug("SSH into Netscaler to rules still persist") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + + cmd = "show server" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertNotEqual( + result.count(self.vm_2.ipaddress), + 0, + "The server should be present in netscaler after VM stop" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_04_migrate_user_vm(self): + """Test migrate user VM with LB""" + + # Validate the following + # 1. Create 2 instances and add these two for load balancing + # 2. migrate one Vm to another host. + # 3. Test whether the request are sent to stopped user VM after migrate + # 4. In netscaler, the LB rules are still configured. + + hosts = Host.list( + self.apiclient, + zoneid=self.vm_2.zoneid, + type='Routing' + ) + + self.assertEqual( + isinstance(hosts, list), + True, + "Check the number of hosts in the zone" + ) + self.assertGreaterEqual( + len(hosts), + 2, + "Atleast 2 hosts should be present in a zone for VM migration" + ) + + # Remove the host of current VM from the hosts list + hosts[:] = [host for host in hosts if host.id != self.vm_2.hostid] + + host = hosts[0] + self.debug("Migrating VM-ID: %s to Host: %s" % (self.vm_2.id, host.id)) + + cmd = migrateVirtualMachine.migrateVirtualMachineCmd() + cmd.hostid = host.id + cmd.virtualmachineid = self.medium_virtual_machine.id + self.apiclient.migrateVirtualMachine(cmd) + + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.vm_2.id + ) + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.hostid, + host.id, + "Check destination hostID of migrated VM" + ) + self.debug("Migrated VM-ID: %s to Host: %s" % (self.vm_2.id, host.id)) + try: + self.debug( + "Verifying request served by only running instances") + hostnames = [] + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_2 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertNotEqual( + hostnames[0], + hostnames[1], + "Both request should be served by different instances" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip_1.ipaddress.ipaddress, + e)) + self.debug("SSH into Netscaler to rules still persist") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + + cmd = "show server" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertNotEqual( + result.count(self.vm_2.ipaddress), + 0, + "The server should be present in netscaler after migrate" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_05_reboot_user_vm(self): + """Test reboot user VM with LB""" + + # Validate the following + # 1. Create 2 instances and add these two for load balancing + # 2. Reboot one of the user VM + # 3. Test whether the request are sent to both VMs after reboot + # 4. In netscaler, LB rules for this VM still remain configured. + + self.debug("Rebooting VM instance: %s" % self.vm_2.name) + self.vm_2.reboot(self.apiclient) + self.debug("Rebooting VM: %s" % self.vm_2.name) + + try: + self.debug( + "Verifying request served by only running instances") + hostnames = [] + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_2 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertNotEqual( + hostnames[0], + hostnames[1], + "Both request should be served by different instances" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip_1.ipaddress.ipaddress, + e)) + self.debug("SSH into Netscaler to rules still persist") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + + cmd = "show server" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertNotEqual( + result.count(self.vm_2.ipaddress), + 0, + "The server should be present in netscaler after reboot" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_06_destroy_user_vm(self): + """Test destroy user VM with LB""" + + # Validate the following + # 1. Create 2 instances and add these two for load balancing + # 2. Destroy one of the user VM + # 3. Until the time the Vm is in "Destroyed" state, the servies + # relating to this Vm will be marked as "Down". + # 4. Once the Vm gets expunged, then the servers and services + # associated with this VM should get deleted and the LB rules + # should not be pointing to this Vm anymore. + + self.debug("Destroying VM instance: %s" % self.vm_2.name) + self.vm_2.delete(self.apiclient) + self.debug("Destroying VM: %s" % self.vm_2.name) + + try: + self.debug( + "Verifying request served by only running instances") + hostnames = [] + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertEqual( + hostnames[0], + hostnames[1], + "Both request should be served by same instance" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip_1.ipaddress.ipaddress, + e)) + delay = list_configurations( + self.apiclient, + name='expunge.delay' + ) + wait = list_configurations( + self.apiclient, + name='expunge.interval' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(delay[0].value) + int(wait[0].value)) + self.debug("SSH into Netscaler to rules still persist") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + + cmd = "show server" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(self.vm_2.ipaddress), + 0, + "The server should not be present in netscaler after destroy" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_07_delete_all_public_ip(self): + """Test delete all public Ip with LB rules""" + + # Validate the following + # 1. Associate 2 public Ips and create load balancing rules in it + # 2. Delete all of the public Ip + # 3. All the LB rules should be removed from that public Ip + # 4. In netscaler, make sure that all LB rules associated with that + # public Ip should get removed. + # 5. All servers and services service to that public Ip get deleted + + self.debug("Deleting public IP: %s from network: %s" % ( + self.public_ip_1.ipaddress.ipaddress, + self.network.name + )) + self.public_ip_1.delete(self.apiclient) + self.debug( + "Public Ip: %s is deleted!" % + self.public_ip_1.ipaddress.ipaddress) + lb_rules = LoadBalancerRule.list( + self.apiclient, + publicipid=self.public_ip_1.ipaddress.id, + listall=True, + ) + self.assertEqual( + lb_rules, + None, + "LB rules associated with the public Ip should get deleted" + ) + self.debug("SSH into Netscaler to verify other resources are deleted") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip_1.ipaddress.ipaddress, + self.lb_rule_1.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Virtual server should get deleted after removing LB rule" + ) + + cmd = "show ip" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(self.public_ip_1.ipaddress.ipaddress), + 0, + "Virtual server should get deleted after removing LB rule" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return diff --git a/test/integration/component/test_netscaler_lb_algo.py b/test/integration/component/test_netscaler_lb_algo.py new file mode 100644 index 00000000000..7248405001b --- /dev/null +++ b/test/integration/component/test_netscaler_lb_algo.py @@ -0,0 +1,2601 @@ +# -*- encoding: utf-8 -*- +# Copyright 2012 Citrix Systems, Inc. Licensed under the +# Apache License, Version 2.0 (the "License"); you may not use this +# file except in compliance with the License. Citrix Systems, Inc. +# reserves all rights not expressly granted by the License. +# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Automatically generated by addcopyright.py at 04/03/2012 + +""" P1 tests for netscaler load balancing +""" +#Import Local Modules +import marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from integration.lib.utils import * +from integration.lib.base import * +from integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test netscaler services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "virtual_machine": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "netscaler": { + "ipaddress": '10.147.40.100', + "username": 'nsroot', + "password": 'nsroot', + "networkdevicetype": 'NetscalerVPXLoadBalancer', + "publicinterface": '1/1', + "privateinterface": '1/1', + "numretries": 2, + "lbdevicededicated": False, + "lbdevicecapacity": 50, + }, + "network_offering_dedicated": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "specifyVlan": False, + "specifyIpRanges": False, + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + "servicecapabilitylist": { + "SourceNat": { + "SupportedSourceNatTypes": "peraccount" + }, + "lb": { + "SupportedLbIsolation": "dedicated" + }, + }, + }, + "network_offering": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "network": { + "name": "Netscaler", + "displaytext": "Netscaler", + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 22, + "openfirewall": False, + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "protocol": "TCP" + }, + "ostypeid": '2b58909b-7d9e-45d9-80d8-e58d0bbcbf07', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode":'advanced' + } + + +class TestLbWithRoundRobin(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbWithRoundRobin, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_lb_with_round_robin(self): + """Test Create LB rule with round robin algorithm + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create LB rule with round robin algorithm + # on it. Verify that "Roundrobin" algorithm is applied when using + # this load balancing rule. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Associating public IP for network: %s" % self.network.id) + + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + ip_with_lb_rule.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s, %s to the LB rule %s" % ( + virtual_machine_1.name, + virtual_machine_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine_1, virtual_machine_2]) + + try: + self.debug( + "Verifying the algorithm used for LB by SSHing into instances") + hostnames = [] + ssh = virtual_machine_1.get_ssh_client( + ipaddress=ip_with_lb_rule.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh = virtual_machine_2.get_ssh_client( + ipaddress=ip_with_lb_rule.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertNotEqual( + hostnames[0], + hostnames[1], + "Hostnames must not be same if round robin algo is used" + ) + + ssh = virtual_machine_1.get_ssh_client( + ipaddress=ip_with_lb_rule.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + self.assertEqual( + hostnames[0], + hostnames[2], + "Alternate Hostnames must be same if roundrobin algo is used" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + e)) + return + + + +class TestLbWithLeastConn(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbWithLeastConn, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_lb_with_least_conn(self): + """Test Create LB rule with least connection algorithm + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create LB rule with round robin algorithm + # on it. Verify that "leastconn" algorithm is applied when using + # this load balancing rule. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Associating public IP for network: %s" % self.network.id) + + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + ip_with_lb_rule.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'leastconn' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s to the LB rule %s" % ( + virtual_machine_1.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine_1]) + self.debug("Creating a firewall rule to open up SSH ports..") + + try: + self.debug( + "Verifying the algorithm used for LB by SSHing into instances") + hostnames = [] + ssh = virtual_machine_1.get_ssh_client( + ipaddress=ip_with_lb_rule.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh = virtual_machine_1.get_ssh_client( + ipaddress=ip_with_lb_rule.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.debug("Adding %s to the LB rule %s" % ( + virtual_machine_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine_2]) + + ssh = virtual_machine_2.get_ssh_client( + ipaddress=ip_with_lb_rule.ipaddress.ipaddress + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result) + self.assertNotEqual( + res.count(virtual_machine_2.name), + 1, + "SSH request should go to second VM(having least connections)" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + e)) + return + + +class TestLbWithSourceIp(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbWithSourceIp, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_lb_with_source_ip(self): + """Test Create LB rule with source Ip algorithm + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create LB rule with round robin algorithm + # on it. Verify that "sourceIp" algorithm is applied when using + # this load balancing rule. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Associating public IP for network: %s" % self.network.id) + + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + ip_with_lb_rule.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'source' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s to the LB rule %s" % ( + virtual_machine_1.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine_1]) + + try: + self.debug( + "Verifying the algorithm used for LB by SSHing into instances") + hostnames = [] + ssh = virtual_machine_1.get_ssh_client( + ipaddress=ip_with_lb_rule.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + res = str(result) + + self.assertEqual( + res.count(virtual_machine_1.name), + 1, + "Request should be sent only to the first VM" + ) + + self.debug("Adding %s to the LB rule %s" % ( + virtual_machine_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine_2]) + + ssh = virtual_machine_1.get_ssh_client( + ipaddress=ip_with_lb_rule.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + res = str(result) + + self.assertEqual( + res.count(virtual_machine_1.name), + 1, + "Request should be sent only to the first VM" + ) + + ssh = virtual_machine_2.get_ssh_client( + ipaddress=ip_with_lb_rule.ipaddress.ipaddress + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result) + + self.assertEqual( + res.count(virtual_machine_1.name), + 1, + "Request should be sent only to the first VM" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + e)) + return + + +class TestLbAlgoRrLc(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbAlgoRrLc, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + # Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_lb_round_robin_to_least_conn(self): + """Test edit LB rule from round robin to least connection algo + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create an Lb rule for couple of Vms using + # "RounbRobin" algorithm. Make sure this algorithm is respected. + # 4. Edit this existing LB rule with "Round robin" algorithm to + # "LeastConn" After the update, Verify that "least Connection" + # algorithm is applied when using this load balancing rule. + + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Trying to create PF rule on IP with LB rule: %s" % + self.public_ip.ipaddress.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s, %s to the LB rule %s" % ( + self.vm_1.name, + self.vm_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) + + try: + self.debug( + "Verifying the roundrobin algo used by SSHing into instances") + hostnames = [] + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_2 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertNotEqual( + hostnames[0], + hostnames[1], + "Hostnames must not be same if round robin algo is used" + ) + + ssh_3 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_3.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + self.assertEqual( + hostnames[0], + hostnames[2], + "Alternate Hostnames must be same if roundrobin algo is used" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip.ipaddress.ipaddress, + e)) + self.debug( + "Updating LB rule: %s with new algorithm: %s" % ( + lb_rule.name, + 'leastconn')) + lb_rule.update(self.apiclient, algorithm='leastconn') + + self.debug( + "Removing virtual machine: %s to test least connection algo" % + self.vm_2.name) + try: + self.debug( + "Verifying the algorithm used for LB by SSHing into instances") + hostnames = [] + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_4 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_4.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.debug("Adding %s to the LB rule %s" % ( + self.vm_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_2]) + + ssh_5 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress + ) + self.debug("Command: hostname") + result = ssh_5.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result) + self.assertNotEqual( + res.count(self.vm_2.name), + 1, + "SSH request should go to second VM(having least connections)" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip.ipaddress.ipaddress, + e)) + return + + +class TestLbAlgoLcRr(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbAlgoLcRr, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + # Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_lb_least_conn_to_round_robin(self): + """Test edit LB rule from least conn to round robin algo + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create an Lb rule for couple of Vms using + # "Leastconn" algorithm. Make sure this algorithm is respected. + # 4. Edit this existing LB rule with "Least conn" algorithm to + # "roundrobin" After the update, Verify that "round robin" + # algorithm is applied when using this load balancing rule. + + self.debug( + "Creating LB rule for IP address: %s with least conn algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'leastconn' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s to the LB rule %s" % ( + self.vm_1.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_1]) + + try: + self.debug( + "Verifying the leastconn algo used by SSHing into instances") + hostnames = [] + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_2 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.debug("Adding %s to the LB rule %s" % ( + self.vm_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_2]) + + ssh_3 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_3.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result) + self.assertNotEqual( + res.count(self.vm_2.name), + 1, + "SSH request should go to second VM(having least connections)" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip.ipaddress.ipaddress, + e)) + self.debug( + "Updating LB rule: %s with new algorithm: %s" % ( + lb_rule.name, + 'roundrobin')) + lb_rule.update(self.apiclient, algorithm='roundrobin') + try: + self.debug( + "Verifying the roundrobin algo used by SSHing into instances") + hostnames = [] + ssh_4 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True) + self.debug("Command: hostname") + result = ssh_4.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_5 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_5.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertNotEqual( + hostnames[0], + hostnames[1], + "Hostnames must not be same if round robin algo is used" + ) + + ssh_6 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_6.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + self.assertEqual( + hostnames[0], + hostnames[2], + "Alternate Hostnames must be same if roundrobin algo is used" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip.ipaddress.ipaddress, + e)) + return + + +class TestLbAlgoRrSb(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbAlgoRrSb, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + # Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_lb_round_robin_to_source(self): + """Test edit LB rule from round robin to source algo + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create an Lb rule for couple of Vms using + # "RounbRobin" algorithm. Make sure this algorithm is respected. + # 4. Edit this existing LB rule with "Round robin" algorithm to + # "Source" After the update, Verify that "Source" + # algorithm is applied when using this load balancing rule. + + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Trying to create PF rule on IP with LB rule: %s" % + self.public_ip.ipaddress.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s, %s to the LB rule %s" % ( + self.vm_1.name, + self.vm_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) + + try: + self.debug( + "Verifying the roundrobin algo used by SSHing into instances") + hostnames = [] + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_2 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertNotEqual( + hostnames[0], + hostnames[1], + "Hostnames must not be same if round robin algo is used" + ) + + ssh_3 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_3.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + self.assertEqual( + hostnames[0], + hostnames[2], + "Alternate Hostnames must be same if roundrobin algo is used" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip.ipaddress.ipaddress, + e)) + self.debug( + "Updating LB rule: %s with new algorithm: %s" % ( + lb_rule.name, + 'source')) + lb_rule.update(self.apiclient, algorithm='source') + + self.debug( + "Removing virtual machine: %s to test source algo" % + self.vm_2.name) + lb_rule.remove(self.apiclient, [self.vm_2]) + + try: + self.debug( + "Verifying the algorithm used for LB by SSHing into instances") + hostnames = [] + ssh_4 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh_4.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + res = str(result) + + self.assertEqual( + res.count(self.vm_1.name), + 1, + "Request should be sent only to the first VM" + ) + + self.debug("Adding %s to the LB rule %s" % ( + self.vm_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_2]) + + ssh_5 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_5.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + res = str(result) + + self.assertEqual( + res.count(self.vm_1.name), + 1, + "Request should be sent only to the first VM" + ) + + ssh_6 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_6.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result) + + self.assertEqual( + res.count(self.vm_1.name), + 1, + "Request should be sent only to the first VM" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip.ipaddress.ipaddress, + e)) + return + + +class TestLbAlgoSbRr(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbAlgoSbRr, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + # Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_lb_source_to_round_robin(self): + """Test edit LB rule from source to round robin algo + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create an Lb rule for couple of Vms using + # "source" algorithm. Make sure this algorithm is respected. + # 4. Edit this existing LB rule with "source" algorithm to + # "roundrobin" After the update, Verify that "round robin" + # algorithm is applied when using this load balancing rule. + + self.debug( + "Creating LB rule for IP address: %s with source algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'source' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s to the LB rule %s" % ( + self.vm_1.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_1]) + + try: + self.debug( + "Verifying the algorithm used for LB by SSHing into instances") + hostnames = [] + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + res = str(result) + + self.assertEqual( + res.count(self.vm_1.name), + 1, + "Request should be sent only to the first VM" + ) + + self.debug("Adding %s to the LB rule %s" % ( + self.vm_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_2]) + + ssh_2 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + res = str(result) + + self.assertEqual( + res.count(self.vm_1.name), + 1, + "Request should be sent only to the first VM" + ) + + ssh_3 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_3.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result) + + self.assertEqual( + res.count(self.vm_1.name), + 1, + "Request should be sent only to the first VM" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip.ipaddress.ipaddress, + e)) + self.debug( + "Updating LB rule: %s with new algorithm: %s" % ( + lb_rule.name, + 'roundrobin')) + lb_rule.update(self.apiclient, algorithm='roundrobin') + + try: + self.debug( + "Verifying the roundrobin algo used by SSHing into instances") + hostnames = [] + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_4 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_4.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertNotEqual( + hostnames[0], + hostnames[1], + "Hostnames must not be same if round robin algo is used" + ) + + ssh_5 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_5.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + self.assertEqual( + hostnames[0], + hostnames[2], + "Alternate Hostnames must be same if roundrobin algo is used" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip.ipaddress.ipaddress, + e)) + return + + +class TestLbAlgoSbLc(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbAlgoSbLc, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + # Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_lb_source_to_least_conn(self): + """Test edit LB rule from source to least conn algo + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create an Lb rule for couple of Vms using + # "source" algorithm. Make sure this algorithm is respected. + # 4. Edit this existing LB rule with "source" algorithm to + # "leastconn" After the update, Verify that "leastconn" + # algorithm is applied when using this load balancing rule. + + self.debug( + "Creating LB rule for IP address: %s with source algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'source' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s to the LB rule %s" % ( + self.vm_1.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_1]) + + try: + self.debug( + "Verifying the algorithm used for LB by SSHing into instances") + hostnames = [] + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + res = str(result) + + self.assertEqual( + res.count(self.vm_1.name), + 1, + "Request should be sent only to the first VM" + ) + + self.debug("Adding %s to the LB rule %s" % ( + self.vm_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_2]) + + ssh_2 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + res = str(result) + + self.assertEqual( + res.count(self.vm_1.name), + 1, + "Request should be sent only to the first VM" + ) + + ssh_3 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_3.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result) + + self.assertEqual( + res.count(self.vm_1.name), + 1, + "Request should be sent only to the first VM" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip.ipaddress.ipaddress, + e)) + self.debug( + "Updating LB rule: %s with new algorithm: %s" % ( + lb_rule.name, + 'leastconn')) + lb_rule.update(self.apiclient, algorithm='leastconn') + + self.debug( + "Removing virtual machine: %s to test least connection algo" % + self.vm_2.name) + lb_rule.remove(self.apiclient, [self.vm_2]) + try: + self.debug( + "Verifying the algorithm used for LB by SSHing into instances") + hostnames = [] + ssh_4 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_4.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_5 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_5.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.debug("Adding %s to the LB rule %s" % ( + self.vm_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_2]) + + ssh_6 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_6.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result) + self.assertNotEqual( + res.count(self.vm_2.name), + 1, + "SSH request should go to second VM(having least connections)" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip.ipaddress.ipaddress, + e)) + return + + +class TestLbAlgoLcSb(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbAlgoLcSb, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + # Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_lb_leastconn_to_source(self): + """Test edit LB rule from round robin to source algo + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create an Lb rule for couple of Vms using + # "leastconn" algorithm. Make sure this algorithm is respected. + # 4. Edit this existing LB rule with "leastconn" algorithm to + # "Source" After the update, Verify that "Source" + # algorithm is applied when using this load balancing rule. + + self.debug( + "Creating LB rule for IP address: %s with leastconn algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'leastconn' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s to the LB rule %s" % ( + self.vm_1.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_1]) + + try: + self.debug( + "Verifying the algorithm used for LB by SSHing into instances") + hostnames = [] + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_2 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.debug("Adding %s to the LB rule %s" % ( + self.vm_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_2]) + + ssh_3 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_3.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result) + self.assertNotEqual( + res.count(self.vm_2.name), + 1, + "SSH request should go to second VM(having least connections)" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip.ipaddress.ipaddress, + e)) + self.debug( + "Updating LB rule: %s with new algorithm: %s" % ( + lb_rule.name, + 'source')) + lb_rule.update(self.apiclient, algorithm='source') + + self.debug( + "Removing virtual machine: %s to test source algo" % + self.vm_2.name) + lb_rule.remove(self.apiclient, [self.vm_2]) + + try: + self.debug( + "Verifying the algorithm used for LB by SSHing into instances") + hostnames = [] + ssh_4 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh_4.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + res = str(result) + + self.assertEqual( + res.count(self.vm_1.name), + 1, + "Request should be sent only to the first VM" + ) + + self.debug("Adding %s to the LB rule %s" % ( + self.vm_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.vm_2]) + + ssh_5 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_5.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + res = str(result) + + self.assertEqual( + res.count(self.vm_1.name), + 1, + "Request should be sent only to the first VM" + ) + + ssh_6 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_6.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result) + + self.assertEqual( + res.count(self.vm_1.name), + 1, + "Request should be sent only to the first VM" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip.ipaddress.ipaddress, + e)) + return diff --git a/test/integration/component/test_netscaler_lb_sticky.py b/test/integration/component/test_netscaler_lb_sticky.py new file mode 100644 index 00000000000..75647951c8c --- /dev/null +++ b/test/integration/component/test_netscaler_lb_sticky.py @@ -0,0 +1,1019 @@ +# -*- encoding: utf-8 -*- +# Copyright 2012 Citrix Systems, Inc. Licensed under the +# Apache License, Version 2.0 (the "License"); you may not use this +# file except in compliance with the License. Citrix Systems, Inc. +# reserves all rights not expressly granted by the License. +# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Automatically generated by addcopyright.py at 04/03/2012 + +""" P1 tests for netscaler load balancing sticky policy +""" +#Import Local Modules +import marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from integration.lib.utils import * +from integration.lib.base import * +from integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test netscaler services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "virtual_machine": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "netscaler": { + "ipaddress": '10.147.40.100', + "username": 'nsroot', + "password": 'nsroot', + "networkdevicetype": 'NetscalerVPXLoadBalancer', + "publicinterface": '1/1', + "privateinterface": '1/1', + "numretries": 2, + "lbdevicededicated": False, + "lbdevicecapacity": 50, + "port": 22, + }, + "network_offering": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "network": { + "name": "Netscaler", + "displaytext": "Netscaler", + }, + "lbrule": { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 22, + "openfirewall": False, + }, + "ostypeid": '2b58909b-7d9e-45d9-80d8-e58d0bbcbf07', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode":'advanced' + } + + +class TestLbStickyPolicy(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbStickyPolicy, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + # Creating network using the network offering created + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_source_based_roundrobin(self): + """Test Create a "SourceBased" stick policy for a Lb rule with "RoundRobin" algorithm + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "SourceBased" stick policy for a Lb rule with + # "RoundRobin" algorithm + + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + self.public_ip.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='SourceBased', + name='SourceBasedRR', + param={"holdtime": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: SOURCEIP"), + 1, + "'SourceBased' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: ROUNDROBIN"), + 1, + "'ROUNDROBIN' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_02_source_based_source_algo(self): + """Test Create a "SourceBased" stick policy for a Lb rule with "Source" algorithm + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "SourceBased" stick policy for a Lb rule with + # "Source" algorithm + + self.debug( + "Creating LB rule for IP address: %s with source algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'source' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='SourceBased', + name='SourceBasedSource', + param={"holdtime": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: SOURCEIP"), + 1, + "'SourceBased' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: SOURCEIPHASH"), + 1, + "'SOURCE' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_03_source_based_leastconn(self): + """Test Create a "SourceBased" stick policy for a Lb rule with leastconn algo + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "SourceBased" stick policy for a Lb rule with + # "leastconn" algorithm + + self.debug( + "Creating LB rule for IP address: %s with leastconn algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'leastconn' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='SourceBased', + name='SourceBasedLeast', + param={"holdtime": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: SOURCEIP"), + 1, + "'SourceBased' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: LEASTCONNECTION"), + 1, + "'leastconn' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_04_lbcookie_based_roundrobin(self): + """Test Create a "LBCookie" stick policy for a Lb rule with roundrobin algo + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "LBCookie" stick policy for a Lb rule with + # "roundrobin" algorithm + + self.debug( + "Creating LB rule for IP address: %s with roundrobin algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + self.services["lbrule"]["publicport"] = 80 + self.services["lbrule"]["privateport"] = 80 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='LbCookie', + name='LbCookieRR', + param={"holdtime": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: COOKIEINSERT"), + 1, + "'LBCookie' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: ROUNDROBIN"), + 1, + "'ROUNDROBIN' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_05_lbcookie_source_algo(self): + """Test Create a "LBCookie" stick policy for a Lb rule with "Source" algorithm + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "LBCookie" stick policy for a Lb rule with + # "Source" algorithm + + self.debug( + "Creating LB rule for IP address: %s with source algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'source' + self.services["lbrule"]["publicport"] = 80 + self.services["lbrule"]["privateport"] = 80 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='LbCookie', + name='LbCookieSource', + param={"holdtime": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: COOKIEINSERT"), + 1, + "'LbCookie' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: SOURCEIPHASH"), + 1, + "'SOURCE' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_06_lbcookie_leastconn(self): + """Test Create a "LBCookie" stick policy for a Lb rule with leastconn algo + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "LBCookie" stick policy for a Lb rule with + # "leastconn" algorithm + + self.debug( + "Creating LB rule for IP address: %s with leastconn algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'leastconn' + self.services["lbrule"]["publicport"] = 80 + self.services["lbrule"]["privateport"] = 80 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='LBCookie', + name='LbcookieLeastConn', + param={"holdtime": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: COOKIEINSERT"), + 1, + "'LbCookie' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: LEASTCONNECTION"), + 1, + "'leastconn' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_07_appcookie_based_roundrobin(self): + """Test Create a "AppCookie" stick policy for a Lb rule with roundrobin algo + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "AppCookie" stick policy for a Lb rule with + # "roundrobin" algorithm + + self.debug( + "Creating LB rule for IP address: %s with roundrobin algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + self.services["lbrule"]["publicport"] = 80 + self.services["lbrule"]["privateport"] = 80 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='AppCookie', + name='AppCookieRR', + param={"name": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: RULE"), + 1, + "'AppCookie' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: ROUNDROBIN"), + 1, + "'ROUNDROBIN' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_08_appcookie_source_algo(self): + """Test Create a "AppCookie" stick policy for a Lb rule with "Source" + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "AppCookie" stick policy for a Lb rule with + # "Source" algorithm + + self.debug( + "Creating LB rule for IP address: %s with source algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'source' + self.services["lbrule"]["publicport"] = 80 + self.services["lbrule"]["privateport"] = 80 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='AppCookie', + name='AppCookieSource', + param={"name": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: RULE"), + 1, + "'AppCookie' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: SOURCEIPHASH"), + 1, + "'SOURCE' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_09_appcookie_leastconn(self): + """Test Create a "AppCookie" stick policy for a Lb rule with leastconn + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "AppCookie" stick policy for a Lb rule with + # "leastconn" algorithm + + self.debug( + "Creating LB rule for IP address: %s with leastconn algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'leastconn' + self.services["lbrule"]["publicport"] = 80 + self.services["lbrule"]["privateport"] = 80 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='AppCookie', + name='AppCookieLeastConn', + param={"name": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: RULE"), + 1, + "'AppCookie' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: LEASTCONNECTION"), + 1, + "'leastconn' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return diff --git a/test/integration/component/test_network_offering.py b/test/integration/component/test_network_offering.py index 24e388c899e..50f17577871 100644 --- a/test/integration/component/test_network_offering.py +++ b/test/integration/component/test_network_offering.py @@ -21,7 +21,7 @@ from marvin.cloudstackAPI import * from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient import datetime @@ -1576,7 +1576,7 @@ class TestNetworkUpgrade(cloudstackTestCase): vpns = Vpn.list( self.apiclient, publicipid=src_nat.id, - listall=True, + listall=True, ) self.assertEqual( diff --git a/test/integration/component/test_project_configs.py b/test/integration/component/test_project_configs.py index d397d9d2a48..20e2f8af1ed 100644 --- a/test/integration/component/test_project_configs.py +++ b/test/integration/component/test_project_configs.py @@ -20,7 +20,7 @@ from marvin.cloudstackAPI import * from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient import datetime diff --git a/test/integration/component/test_project_usage.py b/test/integration/component/test_project_usage.py index 5ecaa83accd..bbf6205c3a2 100644 --- a/test/integration/component/test_project_usage.py +++ b/test/integration/component/test_project_usage.py @@ -20,7 +20,7 @@ from marvin.cloudstackAPI import * from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient import datetime class Services: diff --git a/test/integration/component/test_projects.py b/test/integration/component/test_projects.py index e2167326db6..fd195436905 100644 --- a/test/integration/component/test_projects.py +++ b/test/integration/component/test_projects.py @@ -20,7 +20,7 @@ from marvin.cloudstackAPI import * from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient import datetime diff --git a/test/integration/component/test_routers.py b/test/integration/component/test_routers.py index 7671e80f814..2b0ca7309e6 100644 --- a/test/integration/component/test_routers.py +++ b/test/integration/component/test_routers.py @@ -17,10 +17,10 @@ import marvin from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * -from marvin import remoteSSHClient from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient #Import System modules import time @@ -77,6 +77,7 @@ class Services: # Algorithm used for load balancing "privateport": 22, "publicport": 2222, + "protocol": 'TCP', }, "fw_rule":{ "startport": 1, diff --git a/test/integration/component/test_security_groups.py b/test/integration/component/test_security_groups.py index 7e49d20446a..68074536f9e 100644 --- a/test/integration/component/test_security_groups.py +++ b/test/integration/component/test_security_groups.py @@ -18,10 +18,10 @@ import marvin from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * -from marvin import remoteSSHClient from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient #Import System modules import time diff --git a/test/integration/component/test_snapshots.py b/test/integration/component/test_snapshots.py index 8ab7ff7281e..05585b5ae68 100644 --- a/test/integration/component/test_snapshots.py +++ b/test/integration/component/test_snapshots.py @@ -20,7 +20,7 @@ from marvin.cloudstackAPI import * from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient class Services: """Test Snapshots Services diff --git a/test/integration/component/test_usage.py b/test/integration/component/test_usage.py index ff41baecd77..1e37abda194 100644 --- a/test/integration/component/test_usage.py +++ b/test/integration/component/test_usage.py @@ -20,7 +20,7 @@ from marvin.cloudstackAPI import * from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient import datetime class Services: diff --git a/test/integration/component/test_volumes.py b/test/integration/component/test_volumes.py index a20770b2851..4caee7d170f 100644 --- a/test/integration/component/test_volumes.py +++ b/test/integration/component/test_volumes.py @@ -20,7 +20,7 @@ from marvin.cloudstackAPI import * from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient #Import System modules import os import urllib diff --git a/test/integration/lib/base.py b/test/integration/lib/base.py index 1f8a2f851c0..04adbc9a030 100644 --- a/test/integration/lib/base.py +++ b/test/integration/lib/base.py @@ -598,7 +598,9 @@ class Template: time.sleep(interval) elif 'Installing' not in template.status: - raise Exception("ErrorInDownload") + raise Exception( + "Error in downloading template: status - %s" % + template.status) elif timeout == 0: break @@ -690,10 +692,12 @@ class Iso: return elif 'Downloaded' not in response.status and \ 'Installing' not in response.status: - raise Exception("ErrorInDownload") + raise Exception( + "Error In Downloading ISO: ISO Status - %s" % + response.status) elif timeout == 0: - raise Exception("TimeoutException") + raise Exception("ISO download Timeout Exception") else: timeout = timeout - 1 return @@ -725,12 +729,12 @@ class PublicIPAddress: if zoneid: cmd.zoneid = zoneid elif "zoneid" in services: - services["zoneid"] + cmd.zoneid = services["zoneid"] if domainid: cmd.domainid = domainid elif "domainid" in services: - services["domainid"] + cmd.domainid = services["domainid"] if networkid: cmd.networkid = networkid @@ -1140,7 +1144,7 @@ class LoadBalancerRule: apiclient.removeFromLoadBalancerRule(cmd) return - def update(self, apiclient, algorithm=None, description=None, name=None): + def update(self, apiclient, algorithm=None, description=None, name=None, **kwargs): """Updates the load balancing rule""" cmd = updateLoadBalancerRule.updateLoadBalancerRuleCmd() cmd.id = self.id @@ -1151,8 +1155,40 @@ class LoadBalancerRule: if name: cmd.name = name + [setattr(cmd, k, v) for k, v in kwargs.items()] return apiclient.updateLoadBalancerRule(cmd) + def createSticky(self, apiclient, methodname, name, description=None, param=None): + """Creates a sticky policy for the LB rule""" + + cmd = createLBStickinessPolicy.createLBStickinessPolicyCmd() + cmd.lbruleid = self.id + cmd.methodname = methodname + cmd.name = name + if description: + cmd.description = description + if param: + cmd.param = [] + for name, value in param.items(): + cmd.param.append({'name': name, 'value': value}) + return apiclient.createLBStickinessPolicy(cmd) + + def deleteSticky(self, apiclient, id): + """Deletes stickyness policy""" + + cmd = deleteLBStickinessPolicy.deleteLBStickinessPolicyCmd() + cmd.id = id + return apiclient.deleteLBStickinessPolicy(cmd) + + @classmethod + def listStickyPolicies(cls, apiclient, lbruleid, **kwargs): + """Lists stickiness policies for load balancing rule""" + + cmd= listLBStickinessPolicies.listLBStickinessPoliciesCmd() + cmd.lbruleid = lbruleid + [setattr(cmd, k, v) for k, v in kwargs.items()] + return apiclient.listLBStickinessPolicies(cmd) + @classmethod def list(cls, apiclient, **kwargs): """List all Load balancing rules matching criteria""" @@ -1401,6 +1437,15 @@ class Network: [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.updateNetwork(cmd)) + def restart(self, apiclient, cleanup=None): + """Restarts the network""" + + cmd = restartNetwork.restartNetworkCmd() + cmd.id = self.id + if cleanup: + cmd.cleanup = cleanup + return(apiclient.restartNetwork(cmd)) + @classmethod def list(cls, apiclient, **kwargs): """List all Networks matching criteria""" diff --git a/test/integration/lib/common.py b/test/integration/lib/common.py index 7740a2873d3..5a644aaf16a 100644 --- a/test/integration/lib/common.py +++ b/test/integration/lib/common.py @@ -18,7 +18,7 @@ import marvin from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient from utils import * from base import * @@ -103,12 +103,12 @@ def download_systemplates_sec_storage(server, services): try: # Login to management server - ssh = remoteSSHClient.remoteSSHClient( + ssh = remoteSSHClient( server["ipaddress"], server["port"], server["username"], server["password"] - ) + ) except Exception: raise Exception("SSH access failted for server with IP address: %s" % server["ipaddess"]) diff --git a/test/integration/lib/utils.py b/test/integration/lib/utils.py index 15e63e285ad..b623f6b503d 100644 --- a/test/integration/lib/utils.py +++ b/test/integration/lib/utils.py @@ -16,7 +16,7 @@ import marvin import time -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient from marvin.cloudstackAPI import * from marvin import cloudstackConnection #from cloudstackConnection import cloudConnection @@ -111,12 +111,7 @@ def is_server_ssh_ready(ipaddress, port, username, password, retries=50): loop_cnt = retries while True: try: - ssh = remoteSSHClient.remoteSSHClient( - ipaddress, - port, - username, - password - ) + ssh = remoteSSHClient(ipaddress, port, username, password) except Exception as e: if loop_cnt == 0: raise e @@ -158,12 +153,7 @@ def get_process_status(hostip, port, username, password, linklocalip, process): """Double hop and returns a process status""" #SSH to the machine - ssh = remoteSSHClient.remoteSSHClient( - hostip, - port, - username, - password - ) + ssh = remoteSSHClient(hostip, port, username, password) ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no " ssh_command = ssh_command + \ "-oUserKnownHostsFile=/dev/null -p 3922 %s %s" % ( diff --git a/test/integration/smoke/test_network.py b/test/integration/smoke/test_network.py index 5938094884f..d61bbe1d69b 100644 --- a/test/integration/smoke/test_network.py +++ b/test/integration/smoke/test_network.py @@ -31,7 +31,7 @@ class Services: def __init__(self): self.services = { - "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', + "ostypeid": '1a568aed-db2d-41ca-b644-416b0bdc067e', # Cent OS 5.3 (64 bit) "mode": 'advanced', # Networking mode: Basic or advanced @@ -457,7 +457,7 @@ class TestPortForwarding(cloudstackTestCase): "SSHing into VM with IP address %s after NAT rule deletion" % self.virtual_machine.ipaddress) - remoteSSHClient.remoteSSHClient( + remoteSSHClient( src_nat_ip_addr.ipaddress, self.virtual_machine.ssh_port, self.virtual_machine.username, @@ -573,7 +573,7 @@ class TestPortForwarding(cloudstackTestCase): "SSHing into VM with IP address %s after NAT rule deletion" % self.virtual_machine.ipaddress) - remoteSSHClient.remoteSSHClient( + remoteSSHClient( ip_address.ipaddress.ipaddress, self.virtual_machine.ssh_port, self.virtual_machine.username, @@ -778,7 +778,7 @@ class TestLoadBalancingRule(cloudstackTestCase): (self.vm_1.ipaddress, src_nat_ip_addr.ipaddress) ) - ssh_1 = remoteSSHClient.remoteSSHClient( + ssh_1 = remoteSSHClient( src_nat_ip_addr.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, @@ -803,7 +803,7 @@ class TestLoadBalancingRule(cloudstackTestCase): self.vm_2.id )) - ssh_2 = remoteSSHClient.remoteSSHClient( + ssh_2 = remoteSSHClient( src_nat_ip_addr.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, @@ -836,7 +836,7 @@ class TestLoadBalancingRule(cloudstackTestCase): self.vm_2.id )) - ssh_1 = remoteSSHClient.remoteSSHClient( + ssh_1 = remoteSSHClient( src_nat_ip_addr.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, @@ -859,7 +859,7 @@ class TestLoadBalancingRule(cloudstackTestCase): with self.assertRaises(Exception): self.debug("Removed all VMs, trying to SSH") - ssh_1 = remoteSSHClient.remoteSSHClient( + ssh_1 = remoteSSHClient( src_nat_ip_addr.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, @@ -969,7 +969,7 @@ class TestLoadBalancingRule(cloudstackTestCase): self.vm_1.id, self.vm_2.id )) - ssh_1 = remoteSSHClient.remoteSSHClient( + ssh_1 = remoteSSHClient( self.non_src_nat_ip.ipaddress.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, @@ -988,7 +988,7 @@ class TestLoadBalancingRule(cloudstackTestCase): self.vm_1.id, self.vm_2.id )) - ssh_2 = remoteSSHClient.remoteSSHClient( + ssh_2 = remoteSSHClient( self.non_src_nat_ip.ipaddress.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, @@ -1016,7 +1016,7 @@ class TestLoadBalancingRule(cloudstackTestCase): self.non_src_nat_ip.ipaddress.ipaddress, self.vm_2.id )) - ssh_1 = remoteSSHClient.remoteSSHClient( + ssh_1 = remoteSSHClient( self.non_src_nat_ip.ipaddress.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, @@ -1042,7 +1042,7 @@ class TestLoadBalancingRule(cloudstackTestCase): self.non_src_nat_ip.ipaddress.ipaddress, self.vm_1.id )) - ssh_1 = remoteSSHClient.remoteSSHClient( + ssh_1 = remoteSSHClient( self.non_src_nat_ip.ipaddress.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, @@ -1195,7 +1195,7 @@ class TestRebootRouter(cloudstackTestCase): try: self.debug("SSH into VM (ID : %s ) after reboot" % self.vm_1.id) - remoteSSHClient.remoteSSHClient( + remoteSSHClient( self.nat_rule.ipaddress, self.services["natrule"]["publicport"], self.vm_1.username, @@ -1273,7 +1273,7 @@ class TestAssignRemoveLB(cloudstackTestCase): ] return - def test_assign_and_removal_elb(self): + def test_assign_and_removal_lb(self): """Test for assign & removing load balancing rule""" # Validate: @@ -1347,7 +1347,7 @@ class TestAssignRemoveLB(cloudstackTestCase): self.vm_2.id )) #Create SSH client for each VM - ssh_1 = remoteSSHClient.remoteSSHClient( + ssh_1 = remoteSSHClient( self.non_src_nat_ip.ipaddress, self.services["lbrule"]["publicport"], self.vm_1.username, @@ -1364,7 +1364,7 @@ class TestAssignRemoveLB(cloudstackTestCase): self.vm_1.id, self.vm_2.id )) - ssh_2 = remoteSSHClient.remoteSSHClient( + ssh_2 = remoteSSHClient( self.non_src_nat_ip.ipaddress, self.services["lbrule"]["publicport"], self.vm_2.username, @@ -1406,7 +1406,7 @@ class TestAssignRemoveLB(cloudstackTestCase): self.vm_1.id, )) # Again make a SSH connection, as previous is not used after LB remove - ssh_1 = remoteSSHClient.remoteSSHClient( + ssh_1 = remoteSSHClient( self.non_src_nat_ip.ipaddress, self.services["lbrule"]["publicport"], self.vm_1.username, @@ -1428,13 +1428,13 @@ class TestAssignRemoveLB(cloudstackTestCase): lb_rule.assign(self.apiclient, [self.vm_3]) try: - ssh_1 = remoteSSHClient.remoteSSHClient( + ssh_1 = remoteSSHClient( self.non_src_nat_ip.ipaddress, self.services["lbrule"]["publicport"], self.vm_1.username, self.vm_1.password ) - ssh_3 = remoteSSHClient.remoteSSHClient( + ssh_3 = remoteSSHClient( self.non_src_nat_ip.ipaddress, self.services["lbrule"]["publicport"], self.vm_3.username, @@ -1599,7 +1599,7 @@ class TestReleaseIP(cloudstackTestCase): # SSH Attempt though public IP should fail with self.assertRaises(Exception): - ssh_2 = remoteSSHClient.remoteSSHClient( + ssh_2 = remoteSSHClient( self.ip_addr.ipaddress, self.services["natrule"]["publicport"], self.virtual_machine.username, diff --git a/test/integration/smoke/test_routers.py b/test/integration/smoke/test_routers.py index 603ca672571..8b60933cfe6 100644 --- a/test/integration/smoke/test_routers.py +++ b/test/integration/smoke/test_routers.py @@ -42,7 +42,7 @@ class Services: { "displayname": "Test VM", "username": "root", - "password": "fr3sca", + "password": "password", "ssh_port": 22, "hypervisor": 'XenServer', "privateport": 22, @@ -54,9 +54,9 @@ class Services: "firstname": "Test", "lastname": "User", "username": "testuser", - "password": "fr3sca", + "password": "password", }, - "ostypeid":'946b031b-0e10-4f4a-a3fc-d212ae2ea07f', + "ostypeid":'1a568aed-db2d-41ca-b644-416b0bdc067e', "sleep": 60, "timeout": 10, "mode": 'advanced', #Networking mode: Basic, Advanced @@ -152,7 +152,7 @@ class TestRouterServices(cloudstackTestCase): zoneid=router.zoneid, type='Routing', state='Up', - virtualmachineid=self.vm_1.id + id=router.hostid ) self.assertEqual( isinstance(hosts, list), @@ -214,7 +214,7 @@ class TestRouterServices(cloudstackTestCase): zoneid=router.zoneid, type='Routing', state='Up', - virtualmachineid=self.vm_1.id + id=router.hostid ) self.assertEqual( isinstance(hosts, list), @@ -400,7 +400,7 @@ class TestRouterServices(cloudstackTestCase): zoneid=router.zoneid, type='Routing', state='Up', - virtualmachineid=self.vm_1.id + id=router.hostid ) self.assertEqual( isinstance(hosts, list), diff --git a/test/integration/smoke/test_secondary_storage.py b/test/integration/smoke/test_secondary_storage.py index 9f60593aa9b..120c4fa0a8f 100644 --- a/test/integration/smoke/test_secondary_storage.py +++ b/test/integration/smoke/test_secondary_storage.py @@ -39,14 +39,6 @@ class Services: "hypervisor": "XenServer", "templatefilter": "self", }, - 1: { - "hypervisor": "KVM", - "templatefilter": "self", - }, - 2: { - "hypervisor": "VMWare", - "templatefilter": "self", - }, }, "sleep": 60, "timeout": 5, @@ -89,6 +81,7 @@ class TestSecStorageServices(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return + @unittest.skip("do not add secondary storage") def test_01_add_sec_storage(self): """Test secondary storage """ @@ -377,4 +370,4 @@ class TestSecStorageServices(cloudstackTestCase): True, "Check whether state of template is ready or not" ) - return \ No newline at end of file + return diff --git a/test/integration/smoke/test_snapshots.py b/test/integration/smoke/test_snapshots.py index 694e60e2b8f..91e65a41a0d 100644 --- a/test/integration/smoke/test_snapshots.py +++ b/test/integration/smoke/test_snapshots.py @@ -17,10 +17,10 @@ import marvin from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * +from marvin.remoteSSHClient import remoteSSHClient from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * -from marvin import remoteSSHClient class Services: diff --git a/test/integration/smoke/test_ssvm.py b/test/integration/smoke/test_ssvm.py index f67d918f91f..0e341d5a74a 100644 --- a/test/integration/smoke/test_ssvm.py +++ b/test/integration/smoke/test_ssvm.py @@ -34,7 +34,7 @@ class Services: self.services = { "host": { "username": 'root', # Credentials for SSH - "password": 'fr3sca', + "password": 'password', "publicport": 22, }, "sleep": 60, @@ -78,7 +78,6 @@ class TestSSVMs(cloudstackTestCase): self.apiclient, systemvmtype='secondarystoragevm', state='Running', - zoneid=self.zone.id ) self.assertEqual( isinstance(list_ssvm_response, list), @@ -196,7 +195,6 @@ class TestSSVMs(cloudstackTestCase): self.apiclient, systemvmtype='consoleproxy', state='Running', - zoneid=self.zone.id ) self.assertEqual( isinstance(list_cpvm_response, list), diff --git a/test/integration/smoke/test_vm_life_cycle.py b/test/integration/smoke/test_vm_life_cycle.py index 40d17665900..b125aa5c768 100644 --- a/test/integration/smoke/test_vm_life_cycle.py +++ b/test/integration/smoke/test_vm_life_cycle.py @@ -17,7 +17,7 @@ import marvin from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * -from marvin import remoteSSHClient +from marvin.remoteSSHClient import remoteSSHClient from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * @@ -42,7 +42,7 @@ class Services: "username": "test", # Random characters are appended in create account to # ensure unique username generated each time - "password": "fr3sca", + "password": "password", }, "small": # Create a small virtual machine instance with disk offering @@ -84,7 +84,7 @@ class Services: "name": "Small Instance", "displaytext": "Small Instance", "cpunumber": 1, - "cpuspeed": 500, + "cpuspeed": 100, "memory": 256 }, "medium": @@ -94,17 +94,17 @@ class Services: "name": "Medium Instance", "displaytext": "Medium Instance", "cpunumber": 1, - "cpuspeed": 1000, - "memory": 1024 + "cpuspeed": 100, + "memory": 256 } }, "iso": # ISO settings for Attach/Detach ISO tests { "displaytext": "Test ISO", "name": "testISO", - "url": "http://iso.linuxquestions.org/download/504/1819/http/gd4.tuwien.ac.at/dsl-4.4.10.iso", + "url": "http://nfs1.lab.vmops.com/isos_32bit/dsl-4.4.10.iso", # Source URL where ISO is located - "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', + "ostypeid": '1a568aed-db2d-41ca-b644-416b0bdc067e', "mode": 'HTTP_DOWNLOAD', # Downloading existing ISO }, "template": { @@ -118,7 +118,7 @@ class Services: "sleep": 60, "timeout": 10, #Migrate VM to hostid - "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', + "ostypeid": '1a568aed-db2d-41ca-b644-416b0bdc067e', # CentOS 5.3 (64-bit) "mode":'advanced', } @@ -751,18 +751,15 @@ class TestVMLifeCycle(cloudstackTestCase): True, "Check the number of hosts in the zone" ) - self.assertEqual( + self.assertGreaterEqual( len(hosts), 2, "Atleast 2 hosts should be present in a zone for VM migration" ) + # Remove the host of current VM from the hosts list + hosts[:] = [host for host in hosts if host.id != self.medium_virtual_machine.hostid] - # Find the host of VM and also the new host to migrate VM. - if self.medium_virtual_machine.hostid == hosts[0].id: - host = hosts[1] - else: - host = hosts[0] - + host = hosts[0] self.debug("Migrating VM-ID: %s to Host: %s" % ( self.medium_virtual_machine.id, host.id diff --git a/test/integration/smoke/test_volumes.py b/test/integration/smoke/test_volumes.py index 7ea16837c26..f6b5e79db90 100644 --- a/test/integration/smoke/test_volumes.py +++ b/test/integration/smoke/test_volumes.py @@ -17,10 +17,10 @@ import marvin from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * +from marvin.remoteSSHClient import remoteSSHClient from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * -from marvin import remoteSSHClient #Import System modules import os import urllib diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index c365684a4bb..5e2c640de06 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -3024,7 +3024,7 @@ Dialogs*/ display: block; width: 119px; text-align: right; - font-size: 13px; + font-size: 12px; margin-top: 2px; } diff --git a/ui/index.jsp b/ui/index.jsp index 3414a8699d6..d36b019c922 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -1583,7 +1583,6 @@ - @@ -1652,6 +1651,7 @@