You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by re...@apache.org on 2015/10/21 14:39:29 UTC

[1/2] git commit: updated refs/heads/master to 39bd17d

Repository: cloudstack
Updated Branches:
  refs/heads/master 97619f325 -> 39bd17d79


Improve Internal Loadbalancer Smoke Test

Added 1VPC 2TIER internal lb roundrobin test
Added 1VPC 1TIER internal lb admin stats test
Refactored existing test

Removed double license and imports

Changed default hypervisor from xen to kvm

Fixed default network acl to default_allow

Renamed test02


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/3b15890b
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/3b15890b
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/3b15890b

Branch: refs/heads/master
Commit: 3b15890b5fb93803fcb037718983ede98eef5203
Parents: 6fe5ae0
Author: Michael Andersen <ma...@schubergphilis.com>
Authored: Wed Oct 14 21:19:45 2015 +0200
Committer: Michael Andersen <ma...@schubergphilis.com>
Committed: Tue Oct 20 08:51:12 2015 +0200

----------------------------------------------------------------------
 test/integration/smoke/test_internal_lb.py | 768 +++++++++++++++++++++---
 1 file changed, 686 insertions(+), 82 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3b15890b/test/integration/smoke/test_internal_lb.py
----------------------------------------------------------------------
diff --git a/test/integration/smoke/test_internal_lb.py b/test/integration/smoke/test_internal_lb.py
index 174782f..da845ea 100644
--- a/test/integration/smoke/test_internal_lb.py
+++ b/test/integration/smoke/test_internal_lb.py
@@ -16,63 +16,303 @@
 # under the License.
 """ Tests for configuring Internal Load Balancing Rules.
 """
-#Import Local Modules
-from marvin.codes import FAILED
-from marvin.cloudstackTestCase import *
-from marvin.cloudstackAPI import *
-from marvin.lib.utils import *
-from marvin.lib.base import *
-from marvin.lib.common import *
+# Import Local Modules
+from marvin.codes import PASS, FAILED
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import (cleanup_resources,
+                              get_process_status)
+from marvin.lib.base import (Domain,
+                             Account,
+                             Configurations,
+                             VPC,
+                             VpcOffering,
+                             ServiceOffering,
+                             NetworkOffering,
+                             Network,
+                             PublicIPAddress,
+                             NATRule,
+                             NetworkACL,
+                             LoadBalancerRule,
+                             ApplicationLoadBalancer,
+                             VirtualMachine,
+                             Template,
+                             FireWallRule,
+                             StaticNATRule,
+                             NetworkACLList
+                             )
+
+from marvin.sshClient import SshClient
+
+
+from marvin.lib.common import (get_zone,
+                               get_domain,
+                               get_template,
+                               list_network_offerings)
+
 from nose.plugins.attrib import attr
 
+import logging
+import time
+import math
+
+
+class Services:
+
+    """Test VPC network services - Port Forwarding Rules Test Data Class.
+    """
+
+    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",
+            },
+            "host1": None,
+            "host2": None,
+            "default_hypervisor": "kvm",
+            "compute_offering": {
+                "name": "Tiny Instance",
+                "displaytext": "Tiny Instance",
+                "cpunumber": 1,
+                "cpuspeed": 100,
+                "memory": 128,
+            },
+            "network_offering": {
+                "name": 'VPC Network offering',
+                "displaytext": 'VPC Network',
+                "guestiptype": 'Isolated',
+                "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,Lb,PortForwarding,UserData,StaticNat,NetworkACL',
+                "traffictype": 'GUEST',
+                "availability": 'Optional',
+                "useVpc": 'on',
+                "serviceProviderList": {
+                    "Vpn": 'VpcVirtualRouter',
+                    "Dhcp": 'VpcVirtualRouter',
+                    "Dns": 'VpcVirtualRouter',
+                    "SourceNat": 'VpcVirtualRouter',
+                    "Lb": 'VpcVirtualRouter',
+                    "PortForwarding": 'VpcVirtualRouter',
+                    "UserData": 'VpcVirtualRouter',
+                    "StaticNat": 'VpcVirtualRouter',
+                    "NetworkACL": 'VpcVirtualRouter'
+                },
+            },
+            "network_offering_internal_lb": {
+                "name": 'VPC Network Internal Lb offering',
+                "displaytext": 'VPC Network internal lb',
+                "guestiptype": 'Isolated',
+                "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL,Lb',
+                "traffictype": 'GUEST',
+                "availability": 'Optional',
+                "useVpc": 'on',
+                "serviceCapabilityList": {
+                    "Lb": {
+                        "SupportedLbIsolation": 'dedicated',
+                        "lbSchemes": 'internal'
+                    }
+                },
+                "serviceProviderList": {
+                    "Dhcp": 'VpcVirtualRouter',
+                    "Dns": 'VpcVirtualRouter',
+                    "SourceNat": 'VpcVirtualRouter',
+                    "PortForwarding": 'VpcVirtualRouter',
+                    "UserData": 'VpcVirtualRouter',
+                    "StaticNat": 'VpcVirtualRouter',
+                    "NetworkACL": 'VpcVirtualRouter',
+                    "Lb": 'InternalLbVm'
+                },
+                "egress_policy": "true",
+            },
+            "vpc_offering": {
+                "name": 'Redundant VPC off',
+                "displaytext": 'Redundant VPC off',
+                "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat',
+                "serviceProviderList": {
+                    "Vpn": 'VpcVirtualRouter',
+                    "Dhcp": 'VpcVirtualRouter',
+                    "Dns": 'VpcVirtualRouter',
+                    "SourceNat": 'VpcVirtualRouter',
+                    "PortForwarding": 'VpcVirtualRouter',
+                    "Lb": 'VpcVirtualRouter',
+                    "UserData": 'VpcVirtualRouter',
+                    "StaticNat": 'VpcVirtualRouter',
+                    "NetworkACL": 'VpcVirtualRouter'
+                },
+                "serviceCapabilityList": {
+                    "SourceNat": {
+                        "RedundantRouter": 'true'
+                    }
+                },
+            },
+            "vpc": {
+                "name": "TestVPC",
+                "displaytext": "TestVPC",
+                "cidr": '10.1.0.0/16'
+            },
+            "network": {
+                "name": "Test Network",
+                "displaytext": "Test Network",
+                "netmask": '255.255.255.0'
+            },
+            "lbrule": {
+                "name": "SSH",
+                "alg": "roundrobin",
+                # Algorithm used for load balancing
+                "privateport": 22,
+                "publicport": 2222,
+                "openfirewall": False,
+                "startport": 22,
+                "endport": 2222,
+                "protocol": "TCP",
+                "cidrlist": '0.0.0.0/0',
+            },
+            "lbrule_http": {
+                "name": "HTTP",
+                "alg": "roundrobin",
+                # Algorithm used for load balancing
+                "privateport": 80,
+                "publicport": 80,
+                "openfirewall": False,
+                "startport": 80,
+                "endport": 80,
+                "protocol": "TCP",
+                "cidrlist": '0.0.0.0/0',
+            },
+            "natrule": {
+                "protocol": "TCP",
+                "cidrlist": '0.0.0.0/0',
+            },
+            "http_rule": {
+                "privateport": 80,
+                "publicport": 80,
+                "startport": 80,
+                "endport": 80,
+                "cidrlist": '0.0.0.0/0',
+                "protocol": "TCP"
+            },
+            "virtual_machine": {
+                "displayname": "Test VM",
+                "username": "root",
+                "password": "password",
+                "ssh_port": 22,
+                "privateport": 22,
+                "publicport": 22,
+                "protocol": 'TCP',
+            },
+            "template_kvm": {
+                "name": "tiny-kvm",
+                "displaytext": "macchinina kvm",
+                "format": "qcow2",
+                "hypervisor": "kvm",
+                "ostype": "Other PV (64-bit)",
+                "url": "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-kvm.qcow2.bz2",
+                "requireshvm": "True",
+            },
+            "template_xen": {
+                "name": "tiny-xen",
+                "displaytext": "macchinina xen",
+                "format": "vhd",
+                "hypervisor": "xen",
+                "ostype": "Other (64-bit)",
+                "url": "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-xen.vhd.bz2",
+                "requireshvm": "True",
+            },
+        }
+
+
 class TestInternalLb(cloudstackTestCase):
+
     """Test Internal LB
     """
 
     @classmethod
     def setUpClass(cls):
+
+        cls.logger = logging.getLogger('TestInternalLb')
+        cls.stream_handler = logging.StreamHandler()
+        cls.logger.setLevel(logging.DEBUG)
+        cls.logger.addHandler(cls.stream_handler)
+
         testClient = super(TestInternalLb, cls).getClsTestClient()
         cls.apiclient = testClient.getApiClient()
-        cls.services = testClient.getParsedTestDataConfig()
+        cls.services = Services().services
 
         cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
         cls.domain = get_domain(cls.apiclient)
-        cls.service_offering = ServiceOffering.create(
+        cls.compute_offering = ServiceOffering.create(
             cls.apiclient,
-            cls.services["service_offerings"]["tiny"]
-        )
-        cls.account = Account.create(cls.apiclient, services=cls.services["account"])
-        cls.template = get_template(
-            cls.apiclient,
-            cls.zone.id,
-            cls.services["ostype"]
+            cls.services["compute_offering"]
         )
 
+        cls.account = Account.create(
+            cls.apiclient, services=cls.services["account"])
+
+        if cls.services["default_hypervisor"] == "kvm":
+            cls.template = Template.register(cls.apiclient, cls.services["template_kvm"], cls.zone.id, hypervisor=cls.services[
+                                             "template_kvm"]["hypervisor"], account=cls.account.name, domainid=cls.domain.id)
+        else:
+            cls.template = Template.register(cls.apiclient, cls.services["template_xen"], cls.zone.id, hypervisor=cls.services[
+                                             "template_xen"]["hypervisor"], account=cls.account.name, domainid=cls.domain.id)
+
         if cls.template == FAILED:
-            assert False, "get_template() failed to return template with description %s" % cls.services["ostype"]
+            assert False, "get_template() failed to return template"
 
-        cls.debug("Successfully created account: %s, id: \
-                   %s" % (cls.account.name,\
+        cls.logger.debug("Successfully created account: %s, id: \
+                   %s" % (cls.account.name,
                           cls.account.id))
+
         cls.cleanup = [cls.account]
+        return
 
-    @attr(tags=["smoke", "advanced"], required_hardware="true")
-    def test_internallb(self):
-        """Test create, delete, assign, remove of internal loadbalancer
-        """   
-           #1) Create and enable network offering with Internal Lb vm service
-        self.networkOffering = NetworkOffering.create(self.apiclient, self.services["network_offering_internal_lb"], conservemode=False)
-        #TODO: SIMENH:modify this test to verify lb rules by sending request from another tier
-        self.networkOffering.update(self.apiclient, state="Enabled")
-
-        #2) Create VPC and network in it
-        vpcOffering = VpcOffering.list(self.apiclient,isdefault=True)
-        self.assert_(vpcOffering is not None and len(vpcOffering)>0, "No VPC offerings found")
-        self.services["vpc"] = {}
-        self.services["vpc"]["name"] = "vpc-internallb"
-        self.services["vpc"]["displaytext"] = "vpc-internallb"
-        self.services["vpc"]["cidr"] = "10.1.1.0/24"
-        vpc = VPC.create(
+    def get_networkoffering_state(self, offering):
+        result = list_network_offerings(self.apiclient, id=offering.id)
+        if result:
+            offering = result[0]
+            return offering.state
+        else:
+            return None
+
+    def create_and_enable_network_serviceoffering(self, services):
+
+        try:
+            # Create offering
+            offering = NetworkOffering.create(
+                self.apiclient, services, conservemode=False)
+
+            self.assertIsNotNone(offering, "Failed to create network offering")
+            self.logger.debug("Created network offering: %s" % offering.id)
+
+            if offering:
+                # Enable offeringq
+                offering.update(self.apiclient, state="Enabled")
+                self.assertEqual(self.get_networkoffering_state(
+                    offering), "Enabled", "Failed to enable network offering")
+
+                self.logger.debug("Enabled network offering: %s" % offering.id)
+                return offering
+
+        except Exception as e:
+            self.fail("Failed to create and enable network offering: %s because of %s" % (
+                offering_name, e))
+
+    def create_vpc(self, name, cidr):
+        print name, cidr
+        try:
+            vpcOffering = VpcOffering.list(self.apiclient, isdefault=True)
+            self.assert_(vpcOffering is not None and len(
+                vpcOffering) > 0, "No VPC offerings found")
+
+            self.services["vpc"] = {}
+            self.services["vpc"]["name"] = name
+            self.services["vpc"]["displaytext"] = name
+            self.services["vpc"]["cidr"] = cidr
+
+            vpc = VPC.create(
                 apiclient=self.apiclient,
                 services=self.services["vpc"],
                 networkDomain="vpc.internallb",
@@ -80,61 +320,425 @@ class TestInternalLb(cloudstackTestCase):
                 zoneid=self.zone.id,
                 account=self.account.name,
                 domainid=self.domain.id
-        )
-        self.assert_(vpc is not None, "VPC creation failed")
-        self.services["vpcnetwork"] = {}
-        self.services["vpcnetwork"]["name"] = "vpcntwk"
-        self.services["vpcnetwork"]["displaytext"] = "vpcntwk"
-        ntwk = Network.create(
-            apiclient=self.apiclient,
-            services=self.services["vpcnetwork"],
+            )
+            self.assertIsNotNone(vpc, "VPC creation failed")
+            self.logger.debug("Created VPC %s" % vpc.id)
+            return vpc
+
+        except Exception as e:
+            self.fail("Failed to create VPC: %s due to %s" % (name, e))
+
+    def create_network_tier(self, name, vpcid, gateway, network_offering):
+        self.services["network"]["name"] = name
+        self.services["network"]["displaytext"] = name
+
+        default_acl = NetworkACLList.list(self.apiclient, name="default_allow")[0]
+
+        try:
+            network = Network.create(
+                apiclient=self.apiclient,
+                services=self.services["network"],
+                accountid=self.account.name,
+                domainid=self.domain.id,
+                networkofferingid=network_offering.id,
+                zoneid=self.zone.id,
+                vpcid=vpcid,
+                gateway=gateway,
+                netmask=self.services["network"]["netmask"],
+                aclid=default_acl.id
+            )
+            self.assertIsNotNone(network, "Network failed to create")
+            self.logger.debug(
+                "Created network %s in VPC %s" % (network.id, vpcid))
+
+            return network
+
+        except Exception as e:
+            raise Exception("Create network failed: %s" % e)
+
+    def deployvm_in_network(self, vpc, networkid):
+
+        try:
+            self.services["virtual_machine"]["networkids"] = networkid
+            vm = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
+                                       templateid=self.template.id,
+                                       zoneid=self.zone.id,
+                                       accountid=self.account.name,
+                                       domainid=self.domain.id,
+                                       serviceofferingid=self.compute_offering.id,
+                                       hypervisor=self.services[
+                                           "template_kvm"]["hypervisor"]
+                                       )
+            self.assertIsNotNone(
+                vm, "Failed to deploy vm in network: %s" % networkid)
+            self.assert_(vm.state == 'Running', "VM is not running")
+            self.logger.debug("Deployed VM id: %s in VPC %s" % (vm.id, vpc.id))
+
+            return vm
+
+        except Exception as e:
+            raise Exception("Deployment failed of VM: %s" % e)
+
+    def create_internal_loadbalancer(self, intport, sport, algorithm, networkid):
+        try:
+            # 5) Create an Internal Load Balancer
+            applb = ApplicationLoadBalancer.create(self.apiclient, services=self.services,
+                                                   name="lbrule",
+                                                   sourceport=sport,
+                                                   instanceport=intport,
+                                                   algorithm=algorithm,
+                                                   scheme="Internal",
+                                                   sourcenetworkid=networkid,
+                                                   networkid=networkid
+                                                   )
+
+            self.assertIsNotNone(applb, "Failed to create loadbalancer")
+            self.logger.debug("Created LB %s in VPC" % applb.id)
+
+            return applb
+
+        except Exception as e:
+            self.fail(e)
+
+    def acquire_publicip(self, vpc, network):
+        self.logger.debug(
+            "Associating public IP for network: %s" % network.name)
+        public_ip = PublicIPAddress.create(
+            self.apiclient,
             accountid=self.account.name,
-            domainid=self.domain.id,
-            networkofferingid=self.networkOffering.id,
             zoneid=self.zone.id,
-            vpcid=vpc.id,
-            gateway="10.1.1.1",
-            netmask="255.255.255.192"
+            domainid=self.account.domainid,
+            networkid=network.id,
+            vpcid=vpc.id
         )
-        self.assertIsNotNone(ntwk, "Network failed to create")
-        self.debug("Network %s created in VPC %s" %(ntwk.id, vpc.id))
+        self.assertIsNotNone(public_ip, "Failed to acquire public IP")
+        self.logger.debug("Associated %s with network %s" % (
+            public_ip.ipaddress.ipaddress,
+            network.id
+        ))
+        return public_ip
 
-        #3) Deploy a vm
-        self.services["virtual_machine"]["networkids"] = ntwk.id
-        vm = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
-            templateid=self.template.id,
-            zoneid=self.zone.id,
-            accountid=self.account.name,
-            domainid= self.domain.id,
-            serviceofferingid=self.service_offering.id,
+    def create_natrule(self, vpc, vm, public_port, private_port, public_ip, network, services=None):
+        self.logger.debug("Creating NAT rule in network for vm with public IP")
+        if not services:
+            self.services["natrule"]["privateport"] = private_port
+            self.services["natrule"]["publicport"] = public_port
+            self.services["natrule"]["startport"] = public_port
+            self.services["natrule"]["endport"] = public_port
+            services = self.services["natrule"]
+
+        nat_rule = NATRule.create(
+            apiclient=self.apiclient,
+            services=services,
+            ipaddressid=public_ip.ipaddress.id,
+            virtual_machine=vm,
+            networkid=network.id
         )
-        self.assert_(vm is not None, "VM failed to deploy")
-        self.assert_(vm.state == 'Running', "VM is not running")
-        self.debug("VM %s deployed in VPC %s" %(vm.id, vpc.id))
-        
-        #4) Create an Internal Load Balancer
-        applb = ApplicationLoadBalancer.create(self.apiclient, services=self.services,
-                name="lbrule",
-                sourceport=22,
-                instanceport=22,
-                algorithm="roundrobin",
-                scheme="internal",
-                sourcenetworkid=ntwk.id,
-                networkid=ntwk.id)
-
-        #5) Assign the VM to the Internal Load Balancer
-        applb.assign(self.apiclient, vms=[vm])
-
-        #6) Remove the vm from the Interanl Load Balancer
-        applb.remove(self.apiclient, vms=[vm])
-
-        #7) Delete the Load Balancer
+        self.assertIsNotNone(
+            nat_rule, "Failed to create NAT Rule for %s" % public_ip.ipaddress.ipaddress)
+        self.logger.debug(
+            "Adding NetworkACL rules to make NAT rule accessible")
+
+        vm.ssh_ip = nat_rule.ipaddress
+        vm.public_ip = nat_rule.ipaddress
+        vm.public_port = int(public_port)
+        return nat_rule
+
+    def get_ssh_client(self, vm, retries):
+        """ Setup ssh client connection and return connection
+        vm requires attributes public_ip, public_port, username, password """
+
+        try:
+            ssh_client = SshClient(
+                vm.public_ip,
+                vm.public_port,
+                vm.username,
+                vm.password,
+                retries
+            )
+        except Exception as e:
+            self.fail("Unable to create ssh connection: " % e)
+
+        self.assertIsNotNone(
+            ssh_client, "Failed to setup ssh connection to vm=%s on public_ip=%s" % (vm.name, vm.public_ip))
+        return ssh_client
+
+    def setup_http_daemon(self, vm):
+        """ Creates a index.html in /tmp with private ip as content and
+            starts httpd daemon on all interfaces port 80 serving /tmp/
+            (only tested on the busybox based tiny vm)
+            vm requires attributes public_ip, public_port, username, password
+        """
+        commands = [
+            # using ip address instead of hostname
+            "/sbin/ip addr show eth0 |grep 'inet '| cut -f6 -d' ' > /tmp/index.html",
+            "/usr/sbin/httpd -v -p 0.0.0.0:80 -h /tmp/"
+        ]
+        try:
+            ssh_client = self.get_ssh_client(vm, 8)
+            for cmd in commands:
+                ssh_client.execute(cmd)
+        except Exception as e:
+            self.fail("Failed to ssh into vm: %s due to %s" % (vm, e))
+
+    def run_ssh_test_accross_hosts(self, clienthost, lb_address, max_requests=30):
+        """ Uses clienthost to run wgets on hosts port 80 expects a unique output from url.
+            returns a list of outputs to evaluate.
+        """
+        # Setup ssh connection
+        ssh_client = self.get_ssh_client(clienthost, 8)
+        self.logger.debug(ssh_client)
+        results = []
+
+        try:
+            for x in range(0, max_requests):
+                cmd_test_http = "/usr/bin/wget -T2 -qO- http://" + \
+                    lb_address + "/ 2>/dev/null"
+                # self.debug( "SSH into VM public address: %s and port: %s"
+                # %(.public_ip, vm.public_port))
+                results.append(ssh_client.execute(cmd_test_http)[0])
+                self.logger.debug(results)
+
+        except Exception as e:
+            self.fail("%s: SSH failed for VM with IP Address: %s" %
+                      (e, clienthost.public_ip))
+
+        return results
+
+    def get_std_deviation(self, data):
+        """ Calculates and outputs a mean, variance and standard deviation from an input list of values """
+        num_val = len(data)
+        mean = sum(data) / num_val
+        sqrt = map(lambda x: math.pow(abs(x - mean), 2), data)
+        variance = (sum(sqrt) / num_val - 1)
+        stddev = math.sqrt(variance)
+        return (mean, variance, stddev)
+
+    def evaluate_http_responses(self, responses, algorithm):
+        """ Evaluates response values from http test and verifies algorithm used"""
+        if algorithm == 'roundrobin':
+            # get a list of unique values
+            unique_values = set(responses)
+            # count the occurence of each value in the responses
+            dataset = [responses.count(value) for value in unique_values]
+
+            if len(set(dataset)) == 1:
+                # all values in dataset are equal, perfect result distribution
+                # woohoo!
+                self.logger.debug(
+                    "HTTP responses are evenly distributed! SUCCESS!")
+                return True
+            else:
+                # calculate mean, var, stddev on dataset
+                mean, variance, stddev = self.get_std_deviation(dataset)
+                for value in dataset:
+                    # determine how much value difference is there from the
+                    # mean
+                    difference = abs(value - mean)
+                    # difference between response count of a host and the mean
+                    # should be less than the standard deviation
+                    self.assertLess(
+                        difference, stddev, "Internal LB RoundRobin test Failed because http responsest are not evenly distributed")
+                    self.logger.debug(
+                        "Response distribution count: %d difference to mean: %d within standard deviation: %d" % (value, mean, stddev))
+                return True
+
+    @attr(tags=["smoke", "advanced"], required_hardware="true")
+    def test_01_internallb_roundrobin_1VPC_3VM_HTTP_port80(self):
+        """Test create, assign, remove of an Internal LB with roundrobin http traffic to 3 vm's
+        """
+        max_http_requests = 30
+        algorithm = "roundrobin"
+        public_lb_port = 80
+        private_http_port = 80
+        public_ssh_start_port = 2000
+        num_app_vms = 3
+
+        self.logger.debug("Starting test_01_internallb_roundrobin_1VPC_3VM_HTTP_port80")
+        # Create and enable network offerings
+        network_offering_guestnet = self.create_and_enable_network_serviceoffering(
+            self.services["network_offering"])
+        network_offering_intlb = self.create_and_enable_network_serviceoffering(
+            self.services["network_offering_internal_lb"])
+
+        # Create VPC
+        vpc = self.create_vpc("vpc_intlb_test01", "10.1.0.0/16")
+
+        # Create network tiers
+        network_guestnet = self.create_network_tier(
+            "guestnet_test01", vpc.id, "10.1.1.1",  network_offering_guestnet)
+        network_internal_lb = self.create_network_tier(
+            "intlb_test01", vpc.id, "10.1.2.1",  network_offering_intlb)
+
+        # Create 1 lb client vm in guestnet network tier
+        client_vm = self.deployvm_in_network(vpc, network_guestnet.id)
+
+        # Create X app vm's in internal lb network tier
+        app_vms = []
+        for x in range(0, num_app_vms):
+            vm = None
+            vm = self.deployvm_in_network(vpc, network_internal_lb.id)
+            app_vms.append(vm)
+
+        # Acquire public ip to access guestnet app vms
+        guestnet_public_ip = self.acquire_publicip(vpc, network_guestnet)
+        intlb_public_ip = self.acquire_publicip(vpc, network_internal_lb)
+
+        # Create nat rule to access client vm
+        self.create_natrule(vpc, client_vm, public_ssh_start_port, 22, guestnet_public_ip, network_guestnet)
+
+        # Create nat rule to access app vms directly and start a http daemon on
+        # the vm
+        public_port = public_ssh_start_port + 1
+        for vm in app_vms:
+            self.create_natrule(vpc, vm, public_port, 22, intlb_public_ip, network_internal_lb)
+            public_port += 1
+            time.sleep(10)
+            # start http daemon on vm's
+            self.setup_http_daemon(vm)
+
+        # Create a internal loadbalancer in the internal lb network tier
+        applb = self.create_internal_loadbalancer( private_http_port, public_lb_port, algorithm, network_internal_lb.id)
+        # wait for the loadbalancer to boot and be configured
+        time.sleep(10)
+        # Assign the 2 VMs to the Internal Load Balancer
+        self.logger.debug("Assigning virtual machines to LB: %s" % applb.id)
+        try:
+            applb.assign(self.apiclient, vms=app_vms)
+        except Exception as e:
+            self.fail(
+                "Failed to assign virtual machine(s) to loadbalancer: %s" % e)
+
+        time.sleep(120)
+        # self.logger.debug(dir(applb))
+        results = self.run_ssh_test_accross_hosts(
+            client_vm, applb.sourceipaddress, max_http_requests)
+        success = self.evaluate_http_responses(results, algorithm)
+        self.assertTrue(success, "Test failed on algorithm: %s" % algorithm)
+
+        self.logger.debug(
+            "Removing virtual machines and networks for test_01_internallb_roundrobin_2VM_port80")
+
+        # Remove the virtual machines from the Internal LoadBalancer
+        self.logger.debug("Remove virtual machines from LB: %s" % applb.id)
+        applb.remove(self.apiclient, vms=app_vms)
+
+        # Remove the Load Balancer
+        self.logger.debug("Deleting LB: %s" % applb.id)
         applb.delete(self.apiclient)
 
+    def get_lb_stats_settings(self):
+        self.logger.debug("Retrieving haproxy stats settings")
+        settings = {}
+        try:
+            settings["stats_port"] = Configurations.list(
+                self.apiclient, name="network.loadbalancer.haproxy.stats.port")[0].value
+            settings["stats_uri"] = Configurations.list(
+                self.apiclient, name="network.loadbalancer.haproxy.stats.uri")[0].value
+            settings["username"], settings["password"] = Configurations.list(
+                self.apiclient, name="network.loadbalancer.haproxy.stats.auth")[0].value.split(":")
+            settings["visibility"] = Configurations.list(
+                self.apiclient, name="network.loadbalancer.haproxy.stats.visibility")[0].value
+            self.logger.debug(settings)
+        except Exception as e:
+            self.fail("Failed to retrieve stats settings " % e)
+
+        return settings
+
+    def verify_lb_stats(self, stats_ip, ssh_client, settings):
+
+        word_to_verify = "uptime"
+
+        url = "http://" + stats_ip + ":" + \
+            settings["stats_port"] + settings["stats_uri"]
+        get_contents = "/usr/bin/wget -T3 -qO- --user=" + \
+            settings["username"] + " --password=" + \
+            settings["password"] + " " + url
+        try:
+            self.logger.debug(
+                "Trying to connect to the haproxy stats url %s" % url)
+            result = ssh_client.execute(get_contents)
+        except Exception as e:
+            self.fail("Failed to verify admin stats url %s from: %s" %
+                      (url, ssh_client))
+        finally:
+            del ssh_client
+
+        found = any(word_to_verify in word for word in result)
+
+        if found:
+            return True
+        else:
+            return False
+
+    @attr(tags=["smoke", "advanced"], required_hardware="true")
+    def test02_internallb_haproxy_stats_on_all_interfaces(self):
+        """ Test to verify access to loadbalancer haproxy admin stats page
+            when global setting network.loadbalancer.haproxy.stats.visibility is set to 'all'
+            with credentials from global setting network.loadbalancer.haproxy.stats.auth
+            using the uri from global setting network.loadbalancer.haproxy.stats.uri"""
+
+        self.logger.debug(
+            "Starting test_02_internallb_haproxy_stats_on_all_interfaces")
+
+        settings = self.get_lb_stats_settings()
+
+        dummy_port = 90
+        network_gw = "10.1.2.1"
+        default_visibility = "global"
+
+        # Update global setting if it is not set to our test default
+        if settings["visibility"] != default_visibility:
+            config_update = Configurations.update(
+                self.apiclient, "network.loadbalancer.haproxy.stats.visibility", default_visibility)
+            self.logger.debug(
+                "Updated global setting stats haproxy.stats.visibility to %s" % (default_visibility))
+            settings = self.get_lb_stats_settings()
+
+        # Create and enable network offering
+        network_offering_intlb = self.create_and_enable_network_serviceoffering(
+            self.services["network_offering_internal_lb"])
+
+        # Create VPC
+        vpc = self.create_vpc("vpc_intlb_test_02", "10.1.0.0/16")
+
+        # Create network tier with internal lb service enabled
+        network_internal_lb = self.create_network_tier(
+            "intlb_test02", vpc.id, network_gw,  network_offering_intlb)
+
+        # Create 1 lb vm in internal lb network tier
+        vm = self.deployvm_in_network(vpc, network_internal_lb.id)
+
+        # Acquire 1 public ip and attach to the internal lb network tier
+        public_ip = self.acquire_publicip(vpc, network_internal_lb)
+
+        # Create an internal loadbalancer in the internal lb network tier
+        applb = self.create_internal_loadbalancer(
+            dummy_port, dummy_port, "leastconn", network_internal_lb.id)
+
+        # Assign the 1 VM to the Internal Load Balancer
+        self.logger.debug("Assigning virtual machines to LB: %s" % applb.id)
+        try:
+            applb.assign(self.apiclient, vms=[vm])
+        except Exception as e:
+            self.fail(
+                "Failed to assign virtual machine(s) to loadbalancer: %s" % e)
+
+        # Create nat rule to access client vm
+        self.create_natrule(
+            vpc, vm, "22", "22", public_ip, network_internal_lb)
+
+        # Verify access to and the contents of the admin stats page on the
+        # private address via a vm in the internal lb tier
+        stats = self.verify_lb_stats(
+            applb.sourceipaddress, self.get_ssh_client(vm, 4), settings)
+        self.assertTrue(stats, "Failed to verify LB HAProxy stats")
+
     @classmethod
     def tearDownClass(cls):
         try:
+            cls.logger.debug("Cleaning up testcase resources")
             cleanup_resources(cls.apiclient, cls.cleanup)
-        except Exception, e:
-            raise Exception("Cleanup failed with %s" % e)
 
+        except Exception as e:
+            raise Exception("Cleanup failed with %s" % e)


[2/2] git commit: updated refs/heads/master to 39bd17d

Posted by re...@apache.org.
Merge pull request #933 from michaelandersen/fix/loadbalancer-test

CLOUDSTACK-8697 - Refactored & Added Internal LB smoke testAdded 1VPC 2TIER internal lb roundrobin test
Added 1VPC 1TIER internal lb admin stats test
Refactored existing test
Thanks @wilderrodrigues for examples and advice!

* pr/933:
  Improve Internal Loadbalancer Smoke Test

Signed-off-by: Remi Bergsma <gi...@remi.nl>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/39bd17d7
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/39bd17d7
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/39bd17d7

Branch: refs/heads/master
Commit: 39bd17d797b5edd285b96ced5065f53531daa212
Parents: 97619f3 3b15890
Author: Remi Bergsma <gi...@remi.nl>
Authored: Wed Oct 21 14:39:08 2015 +0200
Committer: Remi Bergsma <gi...@remi.nl>
Committed: Wed Oct 21 14:39:09 2015 +0200

----------------------------------------------------------------------
 test/integration/smoke/test_internal_lb.py | 768 +++++++++++++++++++++---
 1 file changed, 686 insertions(+), 82 deletions(-)
----------------------------------------------------------------------