From 30039e121b948d1e21cc7b762c6e3fe6ac16a09a Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Thu, 4 Jul 2013 13:31:32 +0530 Subject: [PATCH 01/23] Separate the loadbalancing tests Signed-off-by: Prasanna Santhanam --- test/integration/smoke/test_loadbalance.py | 590 +++++++++++++++++++ test/integration/smoke/test_network.py | 645 --------------------- 2 files changed, 590 insertions(+), 645 deletions(-) create mode 100644 test/integration/smoke/test_loadbalance.py diff --git a/test/integration/smoke/test_loadbalance.py b/test/integration/smoke/test_loadbalance.py new file mode 100644 index 00000000000..97bce105b3a --- /dev/null +++ b/test/integration/smoke/test_loadbalance.py @@ -0,0 +1,590 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin import remoteSSHClient +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from nose.plugins.attrib import attr +#Import System modules +import time + +_multiprocess_shared_ = True + +class Services: + """Test Network Services + """ + + def __init__(self): + self.services = { + "ostype": "CentOS 5.3 (64-bit)", + # Cent OS 5.3 (64 bit) + "lb_switch_wait": 10, + # Time interval after which LB switches the requests + "sleep": 60, + "timeout":10, + "network_offering": { + "name": 'Test Network offering', + "displaytext": 'Test Network offering', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + }, + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + # in MHz + "memory": 256, + # In MBs + }, + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + "password": "password", + }, + "server": + { + "displayname": "Small Instance", + "username": "root", + "password": "password", + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "ssh_port": 22, + "protocol": 'TCP', + }, + "natrule": + { + "privateport": 22, + "publicport": 2222, + "protocol": "TCP" + }, + "lbrule": + { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "protocol": 'TCP' + } + } + +class TestLoadBalance(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = super(TestLoadBalance, 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) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + #Create an account, network, VM and IP addresses + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.name, + domainid=cls.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.name, + domainid=cls.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls.non_src_nat_ip = PublicIPAddress.create( + cls.api_client, + cls.account.name, + cls.zone.id, + cls.account.domainid, + cls.services["server"] + ) + # Open up firewall port for SSH + cls.fw_rule = FireWallRule.create( + cls.api_client, + ipaddressid=cls.non_src_nat_ip.ipaddress.id, + protocol=cls.services["lbrule"]["protocol"], + cidrlist=['0.0.0.0/0'], + startport=cls.services["lbrule"]["publicport"], + endport=cls.services["lbrule"]["publicport"] + ) + cls._cleanup = [ + cls.account, + cls.service_offering + ] + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.cleanup = [] + return + + def tearDown(self): + cleanup_resources(self.apiclient, self.cleanup) + return + + @classmethod + def tearDownClass(cls): + cleanup_resources(cls.api_client, cls._cleanup) + return + + def try_ssh(self, src_nat_ip_addr, hostnames): + try: + self.debug( + "SSH into VM (IPaddress: %s) & NAT Rule (Public IP: %s)" % + (self.vm_1.ipaddress, src_nat_ip_addr.ipaddress) + ) + # If Round Robin Algorithm is chosen, + # each ssh command should alternate between VMs + + ssh_1 = remoteSSHClient( + src_nat_ip_addr.ipaddress, + self.services['lbrule']["publicport"], + self.vm_1.username, + self.vm_1.password + ) + hostnames.append(ssh_1.execute("hostname")[0]) + self.debug(hostnames) + except Exception as e: + self.fail("%s: SSH failed for VM with IP Address: %s" % + (e, src_nat_ip_addr.ipaddress)) + time.sleep(self.services["lb_switch_wait"]) + return + + @attr(tags = ["advanced", "advancedns", "smoke", "needle"]) + def test_01_create_lb_rule_src_nat(self): + """Test to create Load balancing rule with source NAT""" + + # Validate the Following: + #1. listLoadBalancerRules should return the added rule + #2. attempt to ssh twice on the load balanced IP + #3. verify using the hostname of the VM + # that round robin is indeed happening as expected + src_nat_ip_addrs = PublicIPAddress.list( + self.apiclient, + account=self.account.name, + domainid=self.account.domainid + ) + self.assertEqual( + isinstance(src_nat_ip_addrs, list), + True, + "Check list response returns a valid list" + ) + src_nat_ip_addr = src_nat_ip_addrs[0] + + # Check if VM is in Running state before creating LB rule + vm_response = VirtualMachine.list( + self.apiclient, + account=self.account.name, + domainid=self.account.domainid + ) + + self.assertEqual( + isinstance(vm_response, list), + True, + "Check list VM returns a valid list" + ) + + self.assertNotEqual( + len(vm_response), + 0, + "Check Port Forwarding Rule is created" + ) + for vm in vm_response: + self.assertEqual( + vm.state, + 'Running', + "VM state should be Running before creating a NAT rule." + ) + + #Create Load Balancer rule and assign VMs to rule + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + src_nat_ip_addr.id, + accountid=self.account.name + ) + self.cleanup.append(lb_rule) + lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) + lb_rules = list_lb_rules( + self.apiclient, + id=lb_rule.id + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "Check list response returns a valid list" + ) + #verify listLoadBalancerRules lists the added load balancing rule + self.assertNotEqual( + len(lb_rules), + 0, + "Check Load Balancer Rule in its List" + ) + self.assertEqual( + lb_rules[0].id, + lb_rule.id, + "Check List Load Balancer Rules returns valid Rule" + ) + + # listLoadBalancerRuleInstances should list all + # instances associated with that LB rule + lb_instance_rules = list_lb_instances( + self.apiclient, + id=lb_rule.id + ) + self.assertEqual( + isinstance(lb_instance_rules, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + len(lb_instance_rules), + 0, + "Check Load Balancer instances Rule in its List" + ) + self.debug("lb_instance_rules Ids: %s, %s" % ( + lb_instance_rules[0].id, + lb_instance_rules[1].id + )) + self.debug("VM ids: %s, %s" % (self.vm_1.id, self.vm_2.id)) + + self.assertIn( + lb_instance_rules[0].id, + [self.vm_1.id, self.vm_2.id], + "Check List Load Balancer instances Rules returns valid VM ID" + ) + + self.assertIn( + lb_instance_rules[1].id, + [self.vm_1.id, self.vm_2.id], + "Check List Load Balancer instances Rules returns valid VM ID" + ) + + + hostnames = [] + self.try_ssh(src_nat_ip_addr, hostnames) + self.try_ssh(src_nat_ip_addr, hostnames) + self.try_ssh(src_nat_ip_addr, hostnames) + self.try_ssh(src_nat_ip_addr, hostnames) + self.try_ssh(src_nat_ip_addr, hostnames) + + self.debug("Hostnames: %s" % str(hostnames)) + self.assertIn( + self.vm_1.name, + hostnames, + "Check if ssh succeeded for server1" + ) + self.assertIn( + self.vm_2.name, + hostnames, + "Check if ssh succeeded for server2" + ) + + #SSH should pass till there is a last VM associated with LB rule + lb_rule.remove(self.apiclient, [self.vm_2]) + + # making hostnames list empty + hostnames[:] = [] + + try: + self.debug("SSHing into IP address: %s after removing VM (ID: %s)" % + ( + src_nat_ip_addr.ipaddress, + self.vm_2.id + )) + + self.try_ssh(src_nat_ip_addr, hostnames) + self.assertIn( + self.vm_1.name, + hostnames, + "Check if ssh succeeded for server1" + ) + except Exception as e: + self.fail("%s: SSH failed for VM with IP Address: %s" % + (e, src_nat_ip_addr.ipaddress)) + + lb_rule.remove(self.apiclient, [self.vm_1]) + + with self.assertRaises(Exception): + self.debug("Removed all VMs, trying to SSH") + self.try_ssh(src_nat_ip_addr, hostnames) + return + + @attr(tags = ["advanced", "advancedns", "smoke"]) + def test_02_create_lb_rule_non_nat(self): + """Test to create Load balancing rule with non source NAT""" + + # Validate the Following: + #1. listLoadBalancerRules should return the added rule + #2. attempt to ssh twice on the load balanced IP + #3. verify using the hostname of the VM that + # round robin is indeed happening as expected + + #Create Load Balancer rule and assign VMs to rule + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + self.non_src_nat_ip.ipaddress.id, + accountid=self.account.name + ) + self.cleanup.append(lb_rule) + lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) + lb_rules = list_lb_rules( + self.apiclient, + id=lb_rule.id + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "Check list response returns a valid list" + ) + #verify listLoadBalancerRules lists the added load balancing rule + self.assertNotEqual( + len(lb_rules), + 0, + "Check Load Balancer Rule in its List" + ) + self.assertEqual( + lb_rules[0].id, + lb_rule.id, + "Check List Load Balancer Rules returns valid Rule" + ) + # listLoadBalancerRuleInstances should list + # all instances associated with that LB rule + lb_instance_rules = list_lb_instances( + self.apiclient, + id=lb_rule.id + ) + self.assertEqual( + isinstance(lb_instance_rules, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + len(lb_instance_rules), + 0, + "Check Load Balancer instances Rule in its List" + ) + + self.assertIn( + lb_instance_rules[0].id, + [self.vm_1.id, self.vm_2.id], + "Check List Load Balancer instances Rules returns valid VM ID" + ) + + self.assertIn( + lb_instance_rules[1].id, + [self.vm_1.id, self.vm_2.id], + "Check List Load Balancer instances Rules returns valid VM ID" + ) + try: + hostnames = [] + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + + self.debug("Hostnames: %s" % str(hostnames)) + self.assertIn( + self.vm_1.name, + hostnames, + "Check if ssh succeeded for server1" + ) + self.assertIn( + self.vm_2.name, + hostnames, + "Check if ssh succeeded for server2" + ) + + #SSH should pass till there is a last VM associated with LB rule + lb_rule.remove(self.apiclient, [self.vm_2]) + self.debug("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % + ( + self.non_src_nat_ip.ipaddress.ipaddress, + self.vm_2.id + )) + # Making host list empty + hostnames[:] = [] + + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.assertIn( + self.vm_1.name, + hostnames, + "Check if ssh succeeded for server1" + ) + self.debug("Hostnames after removing VM2: %s" % str(hostnames)) + except Exception as e: + self.fail("%s: SSH failed for VM with IP Address: %s" % + (e, self.non_src_nat_ip.ipaddress.ipaddress)) + + lb_rule.remove(self.apiclient, [self.vm_1]) + with self.assertRaises(Exception): + self.debug("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % + ( + self.non_src_nat_ip.ipaddress.ipaddress, + self.vm_1.id + )) + self.try_ssh(self.non_src_nat_ip, hostnames) + return + + @attr(tags = ["advanced", "advancedns", "smoke"]) + def test_assign_and_removal_lb(self): + """Test for assign & removing load balancing rule""" + + # Validate: + #1. Verify list API - listLoadBalancerRules lists + # all the rules with the relevant ports + #2. listLoadBalancerInstances will list + # the instances associated with the corresponding rule. + #3. verify ssh attempts should pass as long as there + # is at least one instance associated with the rule + + # Check if VM is in Running state before creating LB rule + vm_response = VirtualMachine.list( + self.apiclient, + account=self.account.name, + domainid=self.account.domainid + ) + + self.assertEqual( + isinstance(vm_response, list), + True, + "Check list VM returns a valid list" + ) + + self.assertNotEqual( + len(vm_response), + 0, + "Check Port Forwarding Rule is created" + ) + for vm in vm_response: + self.assertEqual( + vm.state, + 'Running', + "VM state should be Running before creating a NAT rule." + ) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + self.non_src_nat_ip.ipaddress.id, + self.account.name + ) + lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) + + hostnames = [] + self.try_ssh(self.non_src_nat_ip, hostnames) + self.try_ssh(self.non_src_nat_ip, hostnames) + self.try_ssh(self.non_src_nat_ip, hostnames) + self.try_ssh(self.non_src_nat_ip, hostnames) + self.try_ssh(self.non_src_nat_ip, hostnames) + + self.debug("Hostnames: %s" % str(hostnames)) + self.assertIn( + self.vm_1.name, + hostnames, + "Check if ssh succeeded for server1" + ) + self.assertIn( + self.vm_2.name, + hostnames, + "Check if ssh succeeded for server2" + ) + #Removing VM and assigning another VM to LB rule + lb_rule.remove(self.apiclient, [self.vm_2]) + + # making hostnames list empty + hostnames[:] = [] + + try: + self.debug("SSHing again into IP address: %s with VM (ID: %s) added to LB rule" % + ( + self.non_src_nat_ip.ipaddress, + self.vm_1.id, + )) + self.try_ssh(self.non_src_nat_ip, hostnames) + + self.assertIn( + self.vm_1.name, + hostnames, + "Check if ssh succeeded for server1" + ) + except Exception as e: + self.fail("SSH failed for VM with IP: %s" % + self.non_src_nat_ip.ipaddress) + + lb_rule.assign(self.apiclient, [self.vm_3]) + +# # Making hostnames list empty + hostnames[:] = [] + self.try_ssh(self.non_src_nat_ip, hostnames) + self.try_ssh(self.non_src_nat_ip, hostnames) + self.try_ssh(self.non_src_nat_ip, hostnames) + self.try_ssh(self.non_src_nat_ip, hostnames) + self.try_ssh(self.non_src_nat_ip, hostnames) + self.debug("Hostnames: %s" % str(hostnames)) + self.assertIn( + self.vm_1.name, + hostnames, + "Check if ssh succeeded for server1" + ) + self.assertIn( + self.vm_3.name, + hostnames, + "Check if ssh succeeded for server3" + ) + return \ No newline at end of file diff --git a/test/integration/smoke/test_network.py b/test/integration/smoke/test_network.py index ca671210c18..dad5630eccb 100644 --- a/test/integration/smoke/test_network.py +++ b/test/integration/smoke/test_network.py @@ -585,432 +585,7 @@ class TestPortForwarding(cloudstackTestCase): 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) - template = get_template( - cls.api_client, - cls.zone.id, - cls.services["ostype"] - ) - cls.services["server"]["zoneid"] = cls.zone.id - - #Create an account, network, VM and IP addresses - cls.account = Account.create( - cls.api_client, - cls.services["account"], - admin=True, - domainid=cls.domain.id - ) - cls.service_offering = ServiceOffering.create( - cls.api_client, - cls.services["service_offering"] - ) - cls.vm_1 = VirtualMachine.create( - cls.api_client, - cls.services["server"], - templateid=template.id, - accountid=cls.account.name, - domainid=cls.account.domainid, - serviceofferingid=cls.service_offering.id - ) - cls.vm_2 = VirtualMachine.create( - cls.api_client, - cls.services["server"], - templateid=template.id, - accountid=cls.account.name, - domainid=cls.account.domainid, - serviceofferingid=cls.service_offering.id - ) - cls.non_src_nat_ip = PublicIPAddress.create( - cls.api_client, - cls.account.name, - cls.zone.id, - cls.account.domainid, - cls.services["server"] - ) - # Open up firewall port for SSH - cls.fw_rule = FireWallRule.create( - cls.api_client, - ipaddressid=cls.non_src_nat_ip.ipaddress.id, - protocol=cls.services["lbrule"]["protocol"], - cidrlist=['0.0.0.0/0'], - startport=cls.services["lbrule"]["publicport"], - endport=cls.services["lbrule"]["publicport"] - ) - cls._cleanup = [ - cls.account, - cls.service_offering - ] - - def setUp(self): - self.apiclient = self.testClient.getApiClient() - self.cleanup = [] - return - - def tearDown(self): - cleanup_resources(self.apiclient, self.cleanup) - return - - @classmethod - def tearDownClass(cls): - cleanup_resources(cls.api_client, cls._cleanup) - return - - def try_ssh(self, src_nat_ip_addr, hostnames): - try: - self.debug( - "SSH into VM (IPaddress: %s) & NAT Rule (Public IP: %s)" % - (self.vm_1.ipaddress, src_nat_ip_addr.ipaddress) - ) - - ssh_1 = remoteSSHClient( - src_nat_ip_addr.ipaddress, - self.services['lbrule']["publicport"], - self.vm_1.username, - self.vm_1.password - ) - - # If Round Robin Algorithm is chosen, - # each ssh command should alternate between VMs - # hostnames = [ssh_1.execute("hostname")[0]] - hostnames.append(ssh_1.execute("hostname")[0]) - - except Exception as e: - self.fail("%s: SSH failed for VM with IP Address: %s" % - (e, src_nat_ip_addr.ipaddress)) - - time.sleep(self.services["lb_switch_wait"]) - return - - @attr(tags = ["advanced", "advancedns", "smoke"]) - def test_01_create_lb_rule_src_nat(self): - """Test to create Load balancing rule with source NAT""" - - # Validate the Following: - #1. listLoadBalancerRules should return the added rule - #2. attempt to ssh twice on the load balanced IP - #3. verify using the hostname of the VM - # that round robin is indeed happening as expected - - src_nat_ip_addrs = list_publicIP( - self.apiclient, - account=self.account.name, - domainid=self.account.domainid - ) - self.assertEqual( - isinstance(src_nat_ip_addrs, list), - True, - "Check list response returns a valid list" - ) - src_nat_ip_addr = src_nat_ip_addrs[0] - - # Check if VM is in Running state before creating LB rule - vm_response = VirtualMachine.list( - self.apiclient, - account=self.account.name, - domainid=self.account.domainid - ) - - self.assertEqual( - isinstance(vm_response, list), - True, - "Check list VM returns a valid list" - ) - - self.assertNotEqual( - len(vm_response), - 0, - "Check Port Forwarding Rule is created" - ) - for vm in vm_response: - self.assertEqual( - vm.state, - 'Running', - "VM state should be Running before creating a NAT rule." - ) - - #Create Load Balancer rule and assign VMs to rule - lb_rule = LoadBalancerRule.create( - self.apiclient, - self.services["lbrule"], - src_nat_ip_addr.id, - accountid=self.account.name - ) - self.cleanup.append(lb_rule) - - lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) - - lb_rules = list_lb_rules( - self.apiclient, - id=lb_rule.id - ) - self.assertEqual( - isinstance(lb_rules, list), - True, - "Check list response returns a valid list" - ) - #verify listLoadBalancerRules lists the added load balancing rule - self.assertNotEqual( - len(lb_rules), - 0, - "Check Load Balancer Rule in its List" - ) - self.assertEqual( - lb_rules[0].id, - lb_rule.id, - "Check List Load Balancer Rules returns valid Rule" - ) - - # listLoadBalancerRuleInstances should list all - # instances associated with that LB rule - lb_instance_rules = list_lb_instances( - self.apiclient, - id=lb_rule.id - ) - self.assertEqual( - isinstance(lb_instance_rules, list), - True, - "Check list response returns a valid list" - ) - self.assertNotEqual( - len(lb_instance_rules), - 0, - "Check Load Balancer instances Rule in its List" - ) - self.debug("lb_instance_rules Ids: %s, %s" % ( - lb_instance_rules[0].id, - lb_instance_rules[1].id - )) - self.debug("VM ids: %s, %s" % (self.vm_1.id, self.vm_2.id)) - - self.assertIn( - lb_instance_rules[0].id, - [self.vm_1.id, self.vm_2.id], - "Check List Load Balancer instances Rules returns valid VM ID" - ) - - self.assertIn( - lb_instance_rules[1].id, - [self.vm_1.id, self.vm_2.id], - "Check List Load Balancer instances Rules returns valid VM ID" - ) - - - hostnames = [] - self.try_ssh(src_nat_ip_addr, hostnames) - self.try_ssh(src_nat_ip_addr, hostnames) - self.try_ssh(src_nat_ip_addr, hostnames) - self.try_ssh(src_nat_ip_addr, hostnames) - self.try_ssh(src_nat_ip_addr, hostnames) - - self.debug("Hostnames: %s" % str(hostnames)) - self.assertIn( - self.vm_1.name, - hostnames, - "Check if ssh succeeded for server1" - ) - self.assertIn( - self.vm_2.name, - hostnames, - "Check if ssh succeeded for server2" - ) - - #SSH should pass till there is a last VM associated with LB rule - lb_rule.remove(self.apiclient, [self.vm_2]) - - # making hostnames list empty - hostnames[:] = [] - - try: - self.debug("SSHing into IP address: %s after removing VM (ID: %s)" % - ( - src_nat_ip_addr.ipaddress, - self.vm_2.id - )) - - self.try_ssh(src_nat_ip_addr, hostnames) - self.assertIn( - self.vm_1.name, - hostnames, - "Check if ssh succeeded for server1" - ) - except Exception as e: - self.fail("%s: SSH failed for VM with IP Address: %s" % - (e, src_nat_ip_addr.ipaddress)) - - lb_rule.remove(self.apiclient, [self.vm_1]) - - with self.assertRaises(Exception): - self.debug("Removed all VMs, trying to SSH") - ssh_1 = remoteSSHClient( - src_nat_ip_addr.ipaddress, - self.services['lbrule']["publicport"], - self.vm_1.username, - self.vm_1.password - ) - ssh_1.execute("hostname")[0] - return - - @attr(tags = ["advanced", "advancedns", "smoke"]) - def test_02_create_lb_rule_non_nat(self): - """Test to create Load balancing rule with source NAT""" - - # Validate the Following: - #1. listLoadBalancerRules should return the added rule - #2. attempt to ssh twice on the load balanced IP - #3. verify using the hostname of the VM that - # round robin is indeed happening as expected - - # Check if VM is in Running state before creating LB rule - vm_response = VirtualMachine.list( - self.apiclient, - account=self.account.name, - domainid=self.account.domainid - ) - - self.assertEqual( - isinstance(vm_response, list), - True, - "Check list VM returns a valid list" - ) - - self.assertNotEqual( - len(vm_response), - 0, - "Check Port Forwarding Rule is created" - ) - for vm in vm_response: - self.assertEqual( - vm.state, - 'Running', - "VM state should be Running before creating a NAT rule." - ) - - #Create Load Balancer rule and assign VMs to rule - lb_rule = LoadBalancerRule.create( - self.apiclient, - self.services["lbrule"], - self.non_src_nat_ip.ipaddress.id, - accountid=self.account.name - ) - self.cleanup.append(lb_rule) - - lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) - - lb_rules = list_lb_rules( - self.apiclient, - id=lb_rule.id - ) - - self.assertEqual( - isinstance(lb_rules, list), - True, - "Check list response returns a valid list" - ) - #verify listLoadBalancerRules lists the added load balancing rule - self.assertNotEqual( - len(lb_rules), - 0, - "Check Load Balancer Rule in its List" - ) - self.assertEqual( - lb_rules[0].id, - lb_rule.id, - "Check List Load Balancer Rules returns valid Rule" - ) - # listLoadBalancerRuleInstances should list - # all instances associated with that LB rule - lb_instance_rules = list_lb_instances( - self.apiclient, - id=lb_rule.id - ) - self.assertEqual( - isinstance(lb_instance_rules, list), - True, - "Check list response returns a valid list" - ) - self.assertNotEqual( - len(lb_instance_rules), - 0, - "Check Load Balancer instances Rule in its List" - ) - - self.assertIn( - lb_instance_rules[0].id, - [self.vm_1.id, self.vm_2.id], - "Check List Load Balancer instances Rules returns valid VM ID" - ) - - self.assertIn( - lb_instance_rules[1].id, - [self.vm_1.id, self.vm_2.id], - "Check List Load Balancer instances Rules returns valid VM ID" - ) - try: - hostnames = [] - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - - self.debug("Hostnames: %s" % str(hostnames)) - self.assertIn( - self.vm_1.name, - hostnames, - "Check if ssh succeeded for server1" - ) - self.assertIn( - self.vm_2.name, - hostnames, - "Check if ssh succeeded for server2" - ) - - #SSH should pass till there is a last VM associated with LB rule - lb_rule.remove(self.apiclient, [self.vm_2]) - - self.debug("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % - ( - self.non_src_nat_ip.ipaddress.ipaddress, - self.vm_2.id - )) - # Making host list empty - hostnames[:] = [] - - self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) - self.assertIn( - self.vm_1.name, - hostnames, - "Check if ssh succeeded for server1" - ) - self.debug("Hostnames after removing VM2: %s" % str(hostnames)) - except Exception as e: - self.fail("%s: SSH failed for VM with IP Address: %s" % - (e, self.non_src_nat_ip.ipaddress.ipaddress)) - - lb_rule.remove(self.apiclient, [self.vm_1]) - with self.assertRaises(Exception): - self.debug("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % - ( - self.non_src_nat_ip.ipaddress.ipaddress, - self.vm_1.id - )) - ssh_1 = remoteSSHClient( - self.non_src_nat_ip.ipaddress.ipaddress, - self.services['lbrule']["publicport"], - self.vm_1.username, - self.vm_1.password - ) - ssh_1.execute("hostname")[0] - return class TestRebootRouter(cloudstackTestCase): @@ -1173,226 +748,6 @@ class TestRebootRouter(cloudstackTestCase): return -class TestAssignRemoveLB(cloudstackTestCase): - - def setUp(self): - self.apiclient = self.testClient.getApiClient() - self.services = Services().services - # Get Zone, Domain and templates - self.domain = get_domain(self.apiclient, self.services) - self.zone = get_zone(self.apiclient, self.services) - template = get_template( - self.apiclient, - self.zone.id, - self.services["ostype"] - ) - self.services["server"]["zoneid"] = self.zone.id - - #Create VMs, accounts - self.account = Account.create( - self.apiclient, - self.services["account"], - admin=True, - domainid=self.domain.id - ) - self.service_offering = ServiceOffering.create( - self.apiclient, - self.services["service_offering"] - ) - - self.vm_1 = VirtualMachine.create( - self.apiclient, - self.services["server"], - templateid=template.id, - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering.id - ) - - self.vm_2 = VirtualMachine.create( - self.apiclient, - self.services["server"], - templateid=template.id, - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering.id - ) - - self.vm_3 = VirtualMachine.create( - self.apiclient, - self.services["server"], - templateid=template.id, - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering.id - ) - - self.cleanup = [ - self.account, - self.service_offering - ] - return - - def tearDown(self): - cleanup_resources(self.apiclient, self.cleanup) - return - - def try_ssh(self, src_nat_ip_addr, hostnames): - try: - self.debug( - "SSH into VM (IPaddress: %s) & NAT Rule (Public IP: %s)" % - (self.vm_1.ipaddress, src_nat_ip_addr.ipaddress) - ) - - ssh_1 = remoteSSHClient( - src_nat_ip_addr.ipaddress, - self.services['lbrule']["publicport"], - self.vm_1.username, - self.vm_1.password - ) - - # If Round Robin Algorithm is chosen, - # each ssh command should alternate between VMs - # hostnames = [ssh_1.execute("hostname")[0]] - hostnames.append(ssh_1.execute("hostname")[0]) - - except Exception as e: - self.fail("%s: SSH failed for VM with IP Address: %s" % - (e, src_nat_ip_addr.ipaddress)) - - time.sleep(self.services["lb_switch_wait"]) - return - - @attr(tags = ["advanced", "advancedns", "smoke"]) - def test_assign_and_removal_lb(self): - """Test for assign & removing load balancing rule""" - - # Validate: - #1. Verify list API - listLoadBalancerRules lists - # all the rules with the relevant ports - #2. listLoadBalancerInstances will list - # the instances associated with the corresponding rule. - #3. verify ssh attempts should pass as long as there - # is at least one instance associated with the rule - - src_nat_ip_addrs = list_publicIP( - self.apiclient, - account=self.account.name, - domainid=self.account.domainid - ) - self.assertEqual( - isinstance(src_nat_ip_addrs, list), - True, - "Check list response returns a valid list" - ) - self.non_src_nat_ip = src_nat_ip_addrs[0] - - # Open up firewall port for SSH - fw_rule = FireWallRule.create( - self.apiclient, - ipaddressid=self.non_src_nat_ip.id, - protocol=self.services["lbrule"]["protocol"], - cidrlist=['0.0.0.0/0'], - startport=self.services["lbrule"]["publicport"], - endport=self.services["lbrule"]["publicport"] - ) - - # Check if VM is in Running state before creating LB rule - vm_response = VirtualMachine.list( - self.apiclient, - account=self.account.name, - domainid=self.account.domainid - ) - - self.assertEqual( - isinstance(vm_response, list), - True, - "Check list VM returns a valid list" - ) - - self.assertNotEqual( - len(vm_response), - 0, - "Check Port Forwarding Rule is created" - ) - for vm in vm_response: - self.assertEqual( - vm.state, - 'Running', - "VM state should be Running before creating a NAT rule." - ) - - lb_rule = LoadBalancerRule.create( - self.apiclient, - self.services["lbrule"], - self.non_src_nat_ip.id, - self.account.name - ) - lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) - - hostnames = [] - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - - self.debug("Hostnames: %s" % str(hostnames)) - self.assertIn( - self.vm_1.name, - hostnames, - "Check if ssh succeeded for server1" - ) - self.assertIn( - self.vm_2.name, - hostnames, - "Check if ssh succeeded for server2" - ) - #Removing VM and assigning another VM to LB rule - lb_rule.remove(self.apiclient, [self.vm_2]) - - # making hostnames list empty - hostnames[:] = [] - - try: - self.debug("SSHing again into IP address: %s with VM (ID: %s) added to LB rule" % - ( - self.non_src_nat_ip.ipaddress, - self.vm_1.id, - )) - self.try_ssh(self.non_src_nat_ip, hostnames) - - self.assertIn( - self.vm_1.name, - hostnames, - "Check if ssh succeeded for server1" - ) - except Exception as e: - self.fail("SSH failed for VM with IP: %s" % - self.non_src_nat_ip.ipaddress) - - lb_rule.assign(self.apiclient, [self.vm_3]) - - # Making hostnames list empty - hostnames[:] = [] - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - self.debug("Hostnames: %s" % str(hostnames)) - self.assertIn( - self.vm_1.name, - hostnames, - "Check if ssh succeeded for server1" - ) - self.assertIn( - self.vm_3.name, - hostnames, - "Check if ssh succeeded for server3" - ) - return - class TestReleaseIP(cloudstackTestCase): def setUp(self): From 1e646629fe84fea56371cf75b5f6f05fbdff54a4 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Thu, 4 Jul 2013 13:50:54 +0530 Subject: [PATCH 02/23] CLOUDSTACK-3354: Fix scalevm test After you scale the vm, user is expected (oddly) to update the virtual machine to signal that the PV tools are installed. This tells cloudstack that the VM has been successfully scaled up/down. Signed-off-by: Prasanna Santhanam (cherry picked from commit c8ad4e5ced323d27862b7197a05f022f1a6efd4f) --- test/integration/smoke/test_scale_vm.py | 215 ++++++++++++------------ 1 file changed, 108 insertions(+), 107 deletions(-) diff --git a/test/integration/smoke/test_scale_vm.py b/test/integration/smoke/test_scale_vm.py index fd8d61e58f7..1d1726dc90b 100644 --- a/test/integration/smoke/test_scale_vm.py +++ b/test/integration/smoke/test_scale_vm.py @@ -20,15 +20,13 @@ import marvin from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * -from marvin.remoteSSHClient import remoteSSHClient from marvin.integration.lib.utils import * from marvin.integration.lib.base import * from marvin.integration.lib.common import * from nose.plugins.attrib import attr -#Import System modules -import time _multiprocess_shared_ = True + class Services: """Test VM Life Cycle Services """ @@ -36,17 +34,17 @@ class Services: def __init__(self): self.services = { - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - # Random characters are appended in create account to - # ensure unique username generated each time - "password": "password", - }, - "small": - # Create a small virtual machine instance with disk offering + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended in create account to + # ensure unique username generated each time + "password": "password", + }, + "small": + # Create a small virtual machine instance with disk offering { "displayname": "testserver", "username": "root", # VM creds for SSH @@ -57,34 +55,34 @@ class Services: "publicport": 22, "protocol": 'TCP', }, - "service_offerings": + "service_offerings": { - "small": - { - # Small service offering ID to for change VM - # service offering from medium to small - "name": "SmallInstance", - "displaytext": "SmallInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - "big": - { - # Big service offering ID to for change VM - "name": "BigInstance", - "displaytext": "BigInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 512, - } - }, - #Change this - "template": { - "displaytext": "xs", - "name": "xs", - "passwordenabled": False, + "small": + { + # Small service offering ID to for change VM + # service offering from medium to small + "name": "SmallInstance", + "displaytext": "SmallInstance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + }, + "big": + { + # Big service offering ID to for change VM + "name": "BigInstance", + "displaytext": "BigInstance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 512, + } }, + #Change this + "template": { + "displaytext": "xs", + "name": "xs", + "passwordenabled": False, + }, "sleep": 60, "timeout": 10, #Migrate VM to hostid @@ -92,8 +90,8 @@ class Services: # CentOS 5.3 (64-bit) } -class TestScaleVm(cloudstackTestCase): +class TestScaleVm(cloudstackTestCase): @classmethod def setUpClass(cls): cls.api_client = super(TestScaleVm, cls).getClsTestClient().getApiClient() @@ -105,45 +103,44 @@ class TestScaleVm(cloudstackTestCase): cls.services['mode'] = zone.networktype template = get_template( - cls.api_client, - zone.id, - cls.services["ostype"] - ) + cls.api_client, + zone.id, + cls.services["ostype"] + ) # Set Zones and disk offerings ?? cls.services["small"]["zoneid"] = zone.id cls.services["small"]["template"] = template.id # Create account, service offerings, vm. cls.account = Account.create( - cls.api_client, - cls.services["account"], - domainid=domain.id - ) + cls.api_client, + cls.services["account"], + domainid=domain.id + ) cls.small_offering = ServiceOffering.create( - cls.api_client, - cls.services["service_offerings"]["small"] - ) - + cls.api_client, + cls.services["service_offerings"]["small"] + ) + cls.big_offering = ServiceOffering.create( - cls.api_client, - cls.services["service_offerings"]["big"] - ) + cls.api_client, + cls.services["service_offerings"]["big"] + ) #create a virtual machine cls.virtual_machine = VirtualMachine.create( - cls.api_client, - cls.services["small"], - accountid=cls.account.name, - domainid=cls.account.domainid, - serviceofferingid=cls.small_offering.id, - mode=cls.services["mode"] - ) - #how does it work ?? + cls.api_client, + cls.services["small"], + accountid=cls.account.name, + domainid=cls.account.domainid, + serviceofferingid=cls.small_offering.id, + mode=cls.services["mode"] + ) cls._cleanup = [ - cls.small_offering, - #cls.account - ] + cls.small_offering, + cls.account + ] @classmethod def tearDownClass(cls): @@ -161,65 +158,69 @@ class TestScaleVm(cloudstackTestCase): cleanup_resources(self.apiclient, self.cleanup) return - @attr(tags = ["xenserver", "advanced", "basic"]) + @attr(hypervisor="xenserver") + @attr(tags=["advanced", "basic"]) def test_01_scale_vm(self): """Test scale virtual machine """ # Validate the following # Scale up the vm and see if it scales to the new svc offering and is finally in running state - - - + self.debug("Scaling VM-ID: %s to service offering: %s and state %s" % ( - self.virtual_machine.id, - self.big_offering.id, - self.virtual_machine.state - )) - + self.virtual_machine.id, + self.big_offering.id, + self.virtual_machine.state + )) + cmd = scaleVirtualMachine.scaleVirtualMachineCmd() cmd.serviceofferingid = self.big_offering.id cmd.id = self.virtual_machine.id - self.apiclient.scaleVirtualMachine(cmd) + self.apiclient.scaleVirtualMachine(cmd) - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.virtual_machine.id - ) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine.id + ) self.assertEqual( - isinstance(list_vm_response, list), - True, - "Check list response returns a valid list" - ) + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) self.assertNotEqual( - list_vm_response, - None, - "Check virtual machine is listVirtualMachines" - ) + list_vm_response, + None, + "Check virtual machine is listVirtualMachines" + ) vm_response = list_vm_response[0] - self.assertEqual( - vm_response.id, - self.virtual_machine.id, - "Check virtual machine ID of scaled VM" - ) + vm_response.id, + self.virtual_machine.id, + "Check virtual machine ID of scaled VM" + ) + + # VirtualMachine should be updated to tell cloudstack it has PV tools + # available and successfully scaled. We will only mock that behaviour + # here but it is not expected in production since the VM scaling is not + # guaranteed until tools are installed, vm rebooted + self.virtual_machine.update(self.apiclient, isdynamicallyscalable='true') self.debug("Scaling VM-ID: %s from service offering: %s to new service offering %s and the response says %s" % ( - self.virtual_machine.id, - self.virtual_machine.serviceofferingid, - self.big_offering.id, - vm_response.serviceofferingid - )) + self.virtual_machine.id, + self.virtual_machine.serviceofferingid, + self.big_offering.id, + vm_response.serviceofferingid + )) self.assertEqual( - vm_response.serviceofferingid, - self.big_offering.id, - "Check service offering of the VM" - ) + vm_response.serviceofferingid, + self.big_offering.id, + "Check service offering of the VM" + ) self.assertEqual( - vm_response.state, - 'Running', - "Check the state of VM" - ) + vm_response.state, + 'Running', + "Check the state of VM" + ) return From 968c252ca58fe55285004355dd1060fd1ae9aeb4 Mon Sep 17 00:00:00 2001 From: Harikrishna Patnala Date: Thu, 4 Jul 2013 11:18:35 +0530 Subject: [PATCH 03/23] CLOUDSTACK-3351: Fix add cluster API to set right hypervisor type Signed-off-by: Abhinandan Prateek --- server/src/com/cloud/resource/ResourceManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 054ac40e01b..41c6ad74b96 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -472,7 +472,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, long clusterId = 0; ClusterVO cluster = new ClusterVO(dcId, podId, clusterName); - cluster.setHypervisorType(cmd.getHypervisor()); + cluster.setHypervisorType(hypervisorType.toString()); cluster.setClusterType(clusterType); cluster.setAllocationState(allocationState); From bb6cd764c75f5b781be7a502b77542565909879f Mon Sep 17 00:00:00 2001 From: Nitin Mehta Date: Thu, 4 Jul 2013 14:22:51 +0530 Subject: [PATCH 04/23] CLOUDSTACK-3267 Improved logging by logging the memory values when exception is thrown for the constraint Signed off by : nitin mehta --- .../com/cloud/hypervisor/xen/resource/CitrixResourceBase.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index e07df0b2ab9..c8e00da1f19 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -650,7 +650,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe Long newDynamicMemoryMin = vmSpec.getMinRam(); Long newDynamicMemoryMax = vmSpec.getMaxRam(); if (staticMemoryMin > newDynamicMemoryMin || newDynamicMemoryMax > staticMemoryMax) { - throw new CloudRuntimeException("Cannot scale up the vm because of memory constraint violation: 0 <= memory-static-min <= memory-dynamic-min <= memory-dynamic-max <= memory-static-max "); + throw new CloudRuntimeException("Cannot scale up the vm because of memory constraint violation: " + + "0 <= memory-static-min(" +staticMemoryMin+ ") <= memory-dynamic-min(" +newDynamicMemoryMin+ ") <= memory-dynamic-max(" +newDynamicMemoryMax+ ") <= memory-static-max(" +staticMemoryMax+ ")"); } vm.setMemoryDynamicRange(conn, newDynamicMemoryMin, newDynamicMemoryMax); From 248bea8b27b2ac0dbe00d7f12c72f0858f83746c Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Thu, 4 Jul 2013 14:39:11 +0530 Subject: [PATCH 05/23] ipaddress is included Signed-off-by: Prasanna Santhanam --- test/integration/smoke/test_loadbalance.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/test/integration/smoke/test_loadbalance.py b/test/integration/smoke/test_loadbalance.py index 97bce105b3a..8dd96e589b7 100644 --- a/test/integration/smoke/test_loadbalance.py +++ b/test/integration/smoke/test_loadbalance.py @@ -527,11 +527,11 @@ class TestLoadBalance(cloudstackTestCase): lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) hostnames = [] - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) self.debug("Hostnames: %s" % str(hostnames)) self.assertIn( @@ -556,7 +556,7 @@ class TestLoadBalance(cloudstackTestCase): self.non_src_nat_ip.ipaddress, self.vm_1.id, )) - self.try_ssh(self.non_src_nat_ip, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) self.assertIn( self.vm_1.name, @@ -571,11 +571,11 @@ class TestLoadBalance(cloudstackTestCase): # # Making hostnames list empty hostnames[:] = [] - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) - self.try_ssh(self.non_src_nat_ip, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) + self.try_ssh(self.non_src_nat_ip.ipaddress, hostnames) self.debug("Hostnames: %s" % str(hostnames)) self.assertIn( self.vm_1.name, From 7a8d7eaa6081fe2aadeb72639cf72d68b7f6981a Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Thu, 4 Jul 2013 16:08:18 +0530 Subject: [PATCH 06/23] CLOUDSTACK-3172: Allow creation of private gateway with same Vlan in different VPCs --- server/src/com/cloud/network/NetworkServiceImpl.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 83468718fe6..05df742400f 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -3903,8 +3903,11 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { s_logger.debug("Created private network " + privateNetwork); } else { s_logger.debug("Private network already exists: " + privateNetwork); - throw new InvalidParameterValueException("Private network for the vlan: " + vlan + " and cidr "+ cidr +" already exists " + - " in zone " + _configMgr.getZone(pNtwk.getDataCenterId()).getName()); + //Do not allow multiple private gateways with same Vlan within a VPC + if(vpcId.equals(privateNetwork.getVpcId())){ + throw new InvalidParameterValueException("Private network for the vlan: " + vlan + " and cidr "+ cidr +" already exists " + + "for Vpc "+vpcId+" in zone " + _configMgr.getZone(pNtwk.getDataCenterId()).getName()); + } } //add entry to private_ip_address table From daa4c326aaad4a34e9c45fa77f3cbfd5068d7254 Mon Sep 17 00:00:00 2001 From: Jayapal Date: Thu, 4 Jul 2013 16:33:50 +0530 Subject: [PATCH 07/23] CLOUDSTACK-3312 Updated dhcp_release to listen on eth0 in edithosts.sh --- patches/systemvm/debian/config/root/edithosts.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/systemvm/debian/config/root/edithosts.sh b/patches/systemvm/debian/config/root/edithosts.sh index eaa82927803..513571e69d3 100755 --- a/patches/systemvm/debian/config/root/edithosts.sh +++ b/patches/systemvm/debian/config/root/edithosts.sh @@ -100,7 +100,7 @@ if [ $no_dhcp_release -eq 0 ] then #release previous dhcp lease if present logger -t cloud "edithosts: releasing $ipv4" - dhcp_release lo $ipv4 $(grep $ipv4 $DHCP_LEASES | awk '{print $2}') > /dev/null 2>&1 + dhcp_release eth0 $ipv4 $(grep $ipv4 $DHCP_LEASES | awk '{print $2}') > /dev/null 2>&1 logger -t cloud "edithosts: released $ipv4" fi From 048cf5aae84786d2d3515a3199271e87c0c7bafb Mon Sep 17 00:00:00 2001 From: Gaurav Aradhye Date: Wed, 3 Jul 2013 23:37:52 -0400 Subject: [PATCH 08/23] CLOUDSTACK-2884: Fixed test_04_change_offering_small Added method to compare if two digits are almost equal within given range Signed-off-by: Prasanna Santhanam --- .../smoke/test_service_offerings.py | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/test/integration/smoke/test_service_offerings.py b/test/integration/smoke/test_service_offerings.py index 0213c04cb02..8b6b0133f1c 100644 --- a/test/integration/smoke/test_service_offerings.py +++ b/test/integration/smoke/test_service_offerings.py @@ -273,6 +273,21 @@ class TestServiceOfferings(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return + def isAlmostEqual(self, first_digit, second_digit, range=0): + + digits_equal_within_range = False + + try: + if ((first_digit - range) < second_digit < (first_digit + range)): + digits_equal_within_range = True + + except Exception as e: + self.fail( + "%s: Failed while comparing the numbers %s & %s" % + (e, first_digit, second_digit)) + + return digits_equal_within_range + @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) def test_02_edit_service_offering(self): """Test to update existing service offering""" @@ -431,9 +446,11 @@ class TestServiceOfferings(cloudstackTestCase): self.small_offering.cpuspeed, "Check CPU Speed for small offering" ) - self.assertAlmostEqual( - int(total_mem) / 1024, # In MBs - int(self.small_offering.memory), + self.assertTrue( + self.isAlmostEqual(int(int(total_mem)/1024), + int(self.small_offering.memory), + range=20 + ), "Check Memory(kb) for small offering" ) return From da9552b7f31149e051c5345fbeb0d4858636536e Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Thu, 4 Jul 2013 20:14:03 +0530 Subject: [PATCH 09/23] move isAlmostEqual to utils Signed-off-by: Prasanna Santhanam --- .../smoke/test_service_offerings.py | 25 ++---- tools/marvin/marvin/integration/lib/utils.py | 87 +++++++++++-------- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/test/integration/smoke/test_service_offerings.py b/test/integration/smoke/test_service_offerings.py index 8b6b0133f1c..22273d766e4 100644 --- a/test/integration/smoke/test_service_offerings.py +++ b/test/integration/smoke/test_service_offerings.py @@ -20,7 +20,7 @@ import marvin from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * -from marvin.integration.lib.utils import * +from marvin.integration.lib.utils import isAlmostEqual from marvin.integration.lib.base import * from marvin.integration.lib.common import * from nose.plugins.attrib import attr @@ -273,21 +273,6 @@ class TestServiceOfferings(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - def isAlmostEqual(self, first_digit, second_digit, range=0): - - digits_equal_within_range = False - - try: - if ((first_digit - range) < second_digit < (first_digit + range)): - digits_equal_within_range = True - - except Exception as e: - self.fail( - "%s: Failed while comparing the numbers %s & %s" % - (e, first_digit, second_digit)) - - return digits_equal_within_range - @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) def test_02_edit_service_offering(self): """Test to update existing service offering""" @@ -447,10 +432,10 @@ class TestServiceOfferings(cloudstackTestCase): "Check CPU Speed for small offering" ) self.assertTrue( - self.isAlmostEqual(int(int(total_mem)/1024), - int(self.small_offering.memory), - range=20 - ), + isAlmostEqual(int(int(total_mem) / 1024), + int(self.small_offering.memory), + range=20 + ), "Check Memory(kb) for small offering" ) return diff --git a/tools/marvin/marvin/integration/lib/utils.py b/tools/marvin/marvin/integration/lib/utils.py index 839ec89f4fd..9ab199ab7d4 100644 --- a/tools/marvin/marvin/integration/lib/utils.py +++ b/tools/marvin/marvin/integration/lib/utils.py @@ -35,11 +35,11 @@ def restart_mgmt_server(server): try: # Get the SSH client ssh = is_server_ssh_ready( - server["ipaddress"], - server["port"], - server["username"], - server["password"], - ) + server["ipaddress"], + server["port"], + server["username"], + server["password"], + ) result = ssh.execute("/etc/init.d/cloud-management restart") res = str(result) # Server Stop - OK @@ -57,21 +57,21 @@ def fetch_latest_mail(services, from_mail): # Login to mail server to verify email mail = imaplib.IMAP4_SSL(services["server"]) mail.login( - services["email"], - services["password"] - ) + services["email"], + services["password"] + ) mail.list() mail.select(services["folder"]) date = (datetime.date.today() - datetime.timedelta(1)).strftime("%d-%b-%Y") result, data = mail.uid( - 'search', - None, - '(SENTSINCE {date} HEADER FROM "{mail}")'.format( - date=date, - mail=from_mail - ) - ) + 'search', + None, + '(SENTSINCE {date} HEADER FROM "{mail}")'.format( + date=date, + mail=from_mail + ) + ) # Return False if email is not present if data == []: return False @@ -112,11 +112,11 @@ def is_server_ssh_ready(ipaddress, port, username, password, retries=50, keyPair while True: try: ssh = remoteSSHClient( - host=ipaddress, - port=port, - user=username, - passwd=password, - keyPairFileLocation=keyPairFileLocation) + host=ipaddress, + port=port, + user=username, + passwd=password, + keyPairFileLocation=keyPairFileLocation) except Exception as e: if loop_cnt == 0: raise e @@ -129,9 +129,9 @@ def is_server_ssh_ready(ipaddress, port, username, password, retries=50, keyPair def format_volume_to_ext3(ssh_client, device="/dev/sda"): """Format attached storage to ext3 fs""" cmds = [ - "echo -e 'n\np\n1\n\n\nw' | fdisk %s" % device, - "mkfs.ext3 %s1" % device, - ] + "echo -e 'n\np\n1\n\n\nw' | fdisk %s" % device, + "mkfs.ext3 %s1" % device, + ] for c in cmds: ssh_client.execute(c) @@ -143,15 +143,15 @@ def fetch_api_client(config_file='datacenterCfg'): testClientLogger = logging.getLogger("testClient") asyncTimeout = 3600 return cloudstackAPIClient.CloudStackAPIClient( - marvin.cloudstackConnection.cloudConnection( - mgt.mgtSvrIp, - mgt.port, - mgt.apiKey, - mgt.securityKey, - asyncTimeout, - testClientLogger - ) - ) + marvin.cloudstackConnection.cloudConnection( + mgt.mgtSvrIp, + mgt.port, + mgt.apiKey, + mgt.securityKey, + asyncTimeout, + testClientLogger + ) + ) def get_process_status(hostip, port, username, password, linklocalip, process, hypervisor=None): @@ -164,10 +164,10 @@ def get_process_status(hostip, port, username, password, linklocalip, process, h else: ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no " - ssh_command = ssh_command + \ - "-oUserKnownHostsFile=/dev/null -p 3922 %s %s" % ( - linklocalip, - process) + ssh_command = ssh_command +\ + "-oUserKnownHostsFile=/dev/null -p 3922 %s %s" % ( + linklocalip, + process) # Double hop into router timeout = 5 @@ -183,3 +183,18 @@ def get_process_status(hostip, port, username, password, linklocalip, process, h time.sleep(5) timeout = timeout - 1 return res + + +def isAlmostEqual(self, first_digit, second_digit, range=0): + digits_equal_within_range = False + + try: + if ((first_digit - range) < second_digit < (first_digit + range)): + digits_equal_within_range = True + + except Exception as e: + self.fail( + "%s: Failed while comparing the numbers %s & %s" % + (e, first_digit, second_digit)) + + return digits_equal_within_range From a8a23c4364db6efbf906963c1f7de015320209a5 Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Thu, 4 Jul 2013 21:27:29 +0530 Subject: [PATCH 10/23] CLOUDSTACK-2045:[Multiple IPs Per Nic] This feature is not working well in case of networks with external devices after GC adding missing 'retrun false' for isNetworkReadyForGc for the networks that use external network devices and has secondary IP's associated with nics. --- server/src/com/cloud/network/NetworkModelImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java index 21ef8bcf0ea..407bf705826 100755 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -2143,6 +2143,7 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { // network rules. So prevent network GC. if (secondaryIps != null && !secondaryIps.isEmpty() && networkIsConfiguredForExternalNetworking(network.getDataCenterId(), networkId)) { + return false; } return true; From b3aa11ca394a15b70342bb8ec21da931622c3a8a Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Thu, 4 Jul 2013 21:44:39 +0530 Subject: [PATCH 11/23] Include definition for vm_3 in assign and load balance test Signed-off-by: Prasanna Santhanam --- test/integration/smoke/test_loadbalance.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/integration/smoke/test_loadbalance.py b/test/integration/smoke/test_loadbalance.py index 8dd96e589b7..7bf560cd71a 100644 --- a/test/integration/smoke/test_loadbalance.py +++ b/test/integration/smoke/test_loadbalance.py @@ -145,6 +145,14 @@ class TestLoadBalance(cloudstackTestCase): domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id ) + cls.vm_3 = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.name, + domainid=cls.account.domainid, + serviceofferingid=cls.service_offering.id + ) cls.non_src_nat_ip = PublicIPAddress.create( cls.api_client, cls.account.name, @@ -587,4 +595,4 @@ class TestLoadBalance(cloudstackTestCase): hostnames, "Check if ssh succeeded for server3" ) - return \ No newline at end of file + return From 41fa79f65c8ee3828948dc642dd82f3dcf554968 Mon Sep 17 00:00:00 2001 From: Hugo Trippaers Date: Thu, 4 Jul 2013 16:05:58 +0200 Subject: [PATCH 12/23] The millisecond to second calculation was done with a bit shift of 10. This is in effect a division by 1024, while time in ms should be divided by 1000. The difference of 24 adds up to about a 381 day difference today. This confuses anybody checking the timestamps in the logs. --- server/src/com/cloud/network/NetworkManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index dac6a3a42e7..810c242689b 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -2976,7 +2976,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L public void run() { try { List shutdownList = new ArrayList(); - long currentTime = System.currentTimeMillis() >> 10; + long currentTime = System.currentTimeMillis() / 1000 ; HashMap stillFree = new HashMap(); List networkIds = _networksDao.findNetworksToGarbageCollect(); From 9e2224dd4942ee923cf62027ae8186ea6a8d1e1c Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 5 Jul 2013 11:09:19 +0530 Subject: [PATCH 13/23] print debug message for the waiting time Signed-off-by: Prasanna Santhanam (cherry picked from commit 313177a51e70024f70d02b251afc3d5038a7e488) --- test/integration/smoke/test_routers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/integration/smoke/test_routers.py b/test/integration/smoke/test_routers.py index 6fa08e0ba79..22de29bed72 100644 --- a/test/integration/smoke/test_routers.py +++ b/test/integration/smoke/test_routers.py @@ -850,6 +850,7 @@ class TestRouterServices(cloudstackTestCase): gcwait = config[0] total_wait = int(gcinterval.value) + int(gcwait.value) + self.debug("Waiting %s seconds for network cleanup" % str(total_wait * 2)) # Wait for wait_time * 2 time to cleanup all the resources time.sleep(total_wait * 2) From 1f54e647fbe4a98309363dc46e346fa7415da453 Mon Sep 17 00:00:00 2001 From: Radhika PC Date: Fri, 5 Jul 2013 11:34:58 +0530 Subject: [PATCH 14/23] CLOUDSTACK-2762 --- docs/en-US/add-vm-tier-sharednw.xml | 64 ++++++++++++++ docs/en-US/configure-vpc.xml | 1 + docs/en-US/creating-vms.xml | 97 +++++++++++++++------- docs/en-US/images/addvm-tier-sharednw.png | Bin 0 -> 111465 bytes 4 files changed, 131 insertions(+), 31 deletions(-) create mode 100644 docs/en-US/add-vm-tier-sharednw.xml create mode 100644 docs/en-US/images/addvm-tier-sharednw.png diff --git a/docs/en-US/add-vm-tier-sharednw.xml b/docs/en-US/add-vm-tier-sharednw.xml new file mode 100644 index 00000000000..e1a37c8895c --- /dev/null +++ b/docs/en-US/add-vm-tier-sharednw.xml @@ -0,0 +1,64 @@ + + +%BOOK_ENTITIES; +]> + +
+ Deploying VMs to a Tier and Shared Network + + + Log in to the &PRODUCT; UI as an administrator or end user. + + + In the left navigation, choose Instances. + + + Select the VM you want to work with. + + + Click Add Instance. + + + Select a zone. + + + Select a template or ISO, then follow the steps in the wizard. + For more information about how the templates came to be in this list, see . + + + Ensure that the hardware you have allows starting the selected service offering. + + + Under Networks, select networks for the VM you are launching. + You can deploy a VM to a VPC tier and multiple shared networks. + + + + + + addvm-tier-sharednw.png: adding a VM to a VPC tier and shared network. + + + + + Click Next, review the configuration and click Launch. + Your VM will be deployed to the selected VPC tier and shared network. + + +
diff --git a/docs/en-US/configure-vpc.xml b/docs/en-US/configure-vpc.xml index 45237d21cbb..e0e2ee93f19 100644 --- a/docs/en-US/configure-vpc.xml +++ b/docs/en-US/configure-vpc.xml @@ -26,6 +26,7 @@ + diff --git a/docs/en-US/creating-vms.xml b/docs/en-US/creating-vms.xml index 18995979a80..86d05d3f7bc 100644 --- a/docs/en-US/creating-vms.xml +++ b/docs/en-US/creating-vms.xml @@ -21,35 +21,70 @@ under the License. -->
- Creating VMs - Virtual machines are usually created from a template. Users can also create blank virtual machines. A blank virtual machine is a virtual machine without an OS template. Users can attach an ISO file and install the OS from the CD/DVD-ROM. - You can create a VM without starting it. You can determine whether the VM needs to be started as part of the VM deployment. A request parameter, startVM, in the deployVm API provides this feature. For more information, see the Developer's Guide - To create a VM from a template: - - Log in to the &PRODUCT; UI as an administrator or user. - In the left navigation bar, click Instances. - - Click Add Instance. - - - Select a zone. - - Select a template, then follow the steps in the wizard. For more information about how the templates came to be in this list, see . - Be sure that the hardware you have allows starting the selected service offering. - Click Submit and your VM will be created and started. - For security reason, the internal name of the VM is visible only to the root admin. - - - To create a VM from an ISO: - (XenServer) Windows VMs running on XenServer require PV drivers, which may be provided in the template or added after the VM is created. The PV drivers are necessary for essential management functions such as mounting additional volumes and ISO images, live migration, and graceful shutdown. - - Log in to the &PRODUCT; UI as an administrator or user. - In the left navigation bar, click Instances. - Click Add Instance. - Select a zone. - Select ISO Boot, and follow the steps in the wizard. - Click Submit and your VM will be created and started. - - + Creating VMs + Virtual machines are usually created from a template. Users can also create blank virtual + machines. A blank virtual machine is a virtual machine without an OS template. Users can attach + an ISO file and install the OS from the CD/DVD-ROM. + + You can create a VM without starting it. You can determine whether the VM needs to be + started as part of the VM deployment. A request parameter, startVM, in the deployVm API + provides this feature. For more information, see the Developer's Guide + + To create a VM from a template: + + + Log in to the &PRODUCT; UI as an administrator or user. + + + In the left navigation bar, click Instances. + + + Click Add Instance. + + + Select a zone. + + + Select a template, then follow the steps in the wizard. For more information about how + the templates came to be in this list, see . + + + Be sure that the hardware you have allows starting the selected service offering. + + + Click Submit and your VM will be created and started. + + For security reason, the internal name of the VM is visible only to the root + admin. + + + + To create a VM from an ISO: + + (XenServer) Windows VMs running on XenServer require PV drivers, which may be provided in + the template or added after the VM is created. The PV drivers are necessary for essential + management functions such as mounting additional volumes and ISO images, live migration, and + graceful shutdown. + + + + Log in to the &PRODUCT; UI as an administrator or user. + + + In the left navigation bar, click Instances. + + + Click Add Instance. + + + Select a zone. + + + Select ISO Boot, and follow the steps in the wizard. + + + Click Submit and your VM will be created and started. + + +
- diff --git a/docs/en-US/images/addvm-tier-sharednw.png b/docs/en-US/images/addvm-tier-sharednw.png new file mode 100644 index 0000000000000000000000000000000000000000..e60205f721977a6240f5d4edbe47e33bede5f2cf GIT binary patch literal 111465 zcmagGWmsI>)+G!Cf&`b~?he7BaCdiyV8Puj!5spG6z*;*Tnm@r?oNQn0gQwWFmrPr0j=lDn6{(^mje3{Y>lm4~fot7qeFc4pT1tdpv&suLDt22ELpYL|=m@ldh|tblIH z3^p+t85smB00M2>?V9iDZaa@A^?9~e;&&=p%cSpA2w11B#ur}rtZTlsl$1(YzT0md zu4a%S%gZJ2sMx2W{)LEG;bofyw5jxknB5%X}Vi zpXx29X%;No999r|;+~|GKhjtcuGR!R|58l<&JLT(4RhG}8ek*5u_8$PMajkv-%UA-j{f#aK=8(r(C9%Ma$4P<0yIwhMPab7sZEak+)FAU?9!@!#QPgAL?|dU3IRuA{y999xJfEPkd}?j zr*rg_!ot$#^}(5Aw=jzdZ%fGJQ2&qxBmq@7JlLC2{KeV}CDxT54ju+8js0&S|J|+x z7CM1Z479<16+c{i7H{7FKYILWl7k5=QsqU(Ca*a9Ak((EY5m`GFo;6!L`kdjrQJz< zF#op&{vKR~97bYPi~-)f8X;6+bo(j1%Hnlv=3E#J^<~O=!#HzEyE(bcmx@jUk#Xdo zvzj1Mip(&fxL-e$n7S+}HQqI5mcJ12I=F0p^4gBgc+uDOZ|o*;z$-L-{K zq1HvKFX}%u)9FSyOBjXzG$+)k;(f%iS7FQ_5418=ByDofeYI4(jV+lwOk|$N6mTrK zUR5~ktQUU%{pv(uxR*hrY+r%=4=W-EQ^!D|EfR@h_4d=(* zj09#q`pUQRoPQ^nUL@!b-9@G{@tCWWl57U;_=#x!!?VG=kx=V4C8u~y%O0f20i(_u!jDPP+c@!IKToc|Wt8<3Ukpqy zI~rTJ9_#uIb@+|szhJJ3L087eSCdwJuT{dHa7CD^yIQo|kI+7n2S^U|J02SOwneow zo;THX|8NY;!ue`MH7*GH@E>8aBN`N5Sm5cf-m&}=VW)4NeKViH-ZLEiI6QEZ9D|3A zYP*N5w;QM6q_47T5jz6?+->@0E3w_8U?Gr*_;E$ZrvFoYh2QuUKnewy(Y}_IsoIt> zB9II1ZbLKwX^~~>{EPLL zX&?*IH02eO&zmcWdq(WmC~ImCm~Nzht*Ji|Rr3*j1AqU}TvvRM@5gcW(Xx;t@w1TQ zN5hAWrKUBs9)Wc<`}vsTe9oU-o=2-#_M}+{23XUelWwS}N+IEg>YG>&t#XGoej)br zv&pZK(r*%fgwu5ft2vkaJsrSN3l>jFSE`1ou+8mb)O|37Ol|Eat zzT;dI6>939HUpBZwT$?j(b#JiOCN;Jo7&Aba%-}57-yi~ZC`Qdc}ssjW&y2?Nq>H$ zt?&8W+fE4&J3}%qUONHHLZgXY%PB>=$LeOGOgEuCs6|oh(VEwer&NM_?8xvR8%!!D z4B*RZYpqXROK36jV=u$+(S+z%p4!uS=haRm`*Mq@1y!
EwJm1W!7iIQl)4o>g;zC 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%0D&+{0lyXz_ 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 RZpHxq)RncBN))V~{Xc%QjrITl literal 0 HcmV?d00001 From d1adefe284a38cc194005defc7b38bdde623a180 Mon Sep 17 00:00:00 2001 From: Isaac Chiang Date: Fri, 5 Jul 2013 15:41:09 +0800 Subject: [PATCH 15/23] CLOUDSTACK-3081: Even a dedicate pod operation fails, the system shows "Task Complete" Dedicate zone/pod/cluster/host operations have been fixed --- ui/scripts/system.js | 736 +++++++++++++++++++++---------------------- 1 file changed, 358 insertions(+), 378 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index e00cb7696e8..70b4f8d6195 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -5946,116 +5946,113 @@ } }, - dedicateZone:{ - label: 'Dedicate Zone', - messages: { - confirm: function(args) { - return 'Do you really want to dedicate this zone to a domain/account? '; - }, - notification: function(args) { - return 'Zone Dedicated'; - } + dedicateZone:{ + label: 'Dedicate Zone', + messages: { + confirm: function(args) { + return 'Do you really want to dedicate this zone to a domain/account? '; }, - createForm:{ - title:'Dedicate Zone', - fields:{ - domainId:{ - label:'Domain', - validation:{required:true}, - select:function(args){ - $.ajax({ - url:createURL("listDomains&listAll=true"), - dataType:"json", - async:false, - success: function(json) { - var domainObjs= json.listdomainsresponse.domain; - var items=[]; - - $(domainObjs).each(function() { - items.push({id:this.id ,description:this.name }); - }); - - args.response.success({ - data: items - }); - } - - - }); + notification: function(args) { + return 'Zone Dedicated'; } }, - - accountId:{ - label:'Account', - docID:'helpAccountForDedication', - validation:{required:false} + createForm:{ + title:'Dedicate Zone', + fields:{ + domainId:{ + label:'Domain', + validation:{required:true}, + select:function(args){ + $.ajax({ + url:createURL("listDomains&listAll=true"), + dataType:"json", + async:false, + success: function(json) { + var domainObjs= json.listdomainsresponse.domain; + var items=[]; - } + $(domainObjs).each(function() { + items.push({id:this.id ,description:this.name }); + }); + + args.response.success({ + data: items + }); + } + }); + } + }, + accountId:{ + label:'Account', + docID:'helpAccountForDedication', + validation:{required:false} } - }, - - action: function(args) { - //EXPLICIT DEDICATION - var array2 = []; - if(args.data.accountId != "") - array2.push("&account=" +todb(args.data.accountId)); - - $.ajax({ - url: createURL("dedicateZone&zoneId=" + args.context.physicalResources[0].id + "&domainId=" +args.data.domainId + array2.join("") ), - dataType: "json", - success: function(json) { - var jid = json.dedicatezoneresponse.jobid; - args.response.success({ - _custom: - { jobId: jid - }, - notification: { - poll: pollAsyncJobResult - }, - actionFilter:zoneActionfilter - - }); } - }); - } - - }, - - releaseDedicatedZone:{ - label:'Release Dedicated Zone', - messages:{ - confirm: function(args) { - return 'Do you want to release this dedicated zone ?'; }, - notification: function(args) { - return 'Zone dedication released'; + action: function(args) { + //EXPLICIT DEDICATION + var array2 = []; + if(args.data.accountId != "") + array2.push("&account=" +todb(args.data.accountId)); + + $.ajax({ + url: createURL("dedicateZone&zoneId=" + + args.context.physicalResources[0].id + + "&domainId=" +args.data.domainId + array2.join("")), + dataType: "json", + success: function(json) { + var jid = json.dedicatezoneresponse.jobid; + args.response.success({ + _custom:{ + jobId: jid, + getActionFilter: function() { + return zoneActionfilter; + } + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult } }, - action:function(args){ - $.ajax({ - url:createURL("releaseDedicatedZone&zoneid=" + args.context.physicalResources[0].id), - dataType:"json", - async:true, - success:function(json){ - var jid = json.releasededicatedzoneresponse.jobid; - args.response.success({ - _custom: - { jobId: jid - }, - notification: { - poll: pollAsyncJobResult - }, - actionFilter:zoneActionfilter - - }); - }, - error:function(json){ - args.response.error(parseXMLHttpResponse(json)); + releaseDedicatedZone:{ + label:'Release Dedicated Zone', + messages:{ + confirm: function(args) { + return 'Do you want to release this dedicated zone ?'; + }, + notification: function(args) { + return 'Zone dedication released'; } - }); - - } - }, + }, + action:function(args){ + $.ajax({ + url:createURL("releaseDedicatedZone&zoneid="+ + args.context.physicalResources[0].id), + dataType:"json", + async:true, + success:function(json){ + var jid = json.releasededicatedzoneresponse.jobid; + args.response.success({ + _custom:{ + jobId: jid, + getActionFilter: function() { + return zoneActionfilter; + } + } + }); + }, + error:function(json){ + args.response.error(parseXMLHttpResponse(json)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, 'remove': { label: 'label.action.delete.zone', @@ -9569,120 +9566,115 @@ }, dedicate:{ - label: 'Dedicate Pod', - messages: { - confirm: function(args) { - return 'Do you really want to dedicate this pod to a domain/account? '; + label: 'Dedicate Pod', + messages: { + confirm: function(args) { + return 'Do you really want to dedicate this pod to a domain/account? '; + }, + notification: function(args) { + return 'Pod Dedicated'; + } }, - notification: function(args) { - return 'Pod Dedicated'; - } - }, - createForm:{ - title:'Dedicate Pod', - fields:{ - domainId:{ - label:'Domain', - validation:{required:true}, - select:function(args){ - $.ajax({ - url:createURL("listDomains&listAll=true"), - dataType:"json", - async:false, - success: function(json) { - var domainObjs= json.listdomainsresponse.domain; - var items=[]; + createForm:{ + title:'Dedicate Pod', + fields:{ + domainId:{ + label:'Domain', + validation:{required:true}, + select:function(args){ + $.ajax({ + url:createURL("listDomains&listAll=true"), + dataType:"json", + async:false, + success: function(json) { + var domainObjs= json.listdomainsresponse.domain; + var items=[]; - $(domainObjs).each(function() { - items.push({id:this.id ,description:this.name }); - }); + $(domainObjs).each(function() { + items.push({id:this.id ,description:this.name }); + }); - args.response.success({ - data: items - }); - } - - - }); - } - }, - - accountId:{ - label:'Account', - docID:'helpAccountForDedication', - validation:{required:false} - - } - - - } - }, - action: function(args) { + args.response.success({ + data: items + }); + } + }); + } + }, + accountId:{ + label:'Account', + docID:'helpAccountForDedication', + validation:{required:false} + } + } + }, + action: function(args) { //EXPLICIT DEDICATION - var array2 = []; - if(args.data.accountId != "") - array2.push("&account=" +todb(args.data.accountId)); + var array2 = []; + if(args.data.accountId != "") + array2.push("&account=" +todb(args.data.accountId)); $.ajax({ - url: createURL("dedicatePod&podId=" + args.context.pods[0].id + "&domainId=" +args.data.domainId + array2.join("")), - dataType: "json", - success: function(json) { - var jid = json.dedicatepodresponse.jobid; - args.response.success({ - _custom: - { jobId: jid - }, - notification: { - poll: pollAsyncJobResult - }, - actionFilter:podActionfilter - }); + url: createURL("dedicatePod&podId=" + + args.context.pods[0].id + + "&domainId=" +args.data.domainId + array2.join("")), + dataType: "json", + success: function(json) { + var jid = json.dedicatepodresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getActionFilter: function() { + return podActionfilter; + } + }, + }); }, - error:function(json){ - args.response.error(parseXMLHttpResponse(XMLHttpResponse)); - - } - }); - } - - }, - - release:{ - label:'Release Dedicated Pod', - messages:{ - confirm: function(args) { - return 'Do you want to release this dedicated pod ?'; + error:function(json){ + args.response.error(parseXMLHttpResponse(XMLHttpResponse)); + } + }); }, - notification: function(args) { - return 'Pod dedication released'; + notification: { + poll: pollAsyncJobResult } }, - action:function(args){ - $.ajax({ - url:createURL("releaseDedicatedPod&podid=" + args.context.pods[0].id), - dataType:"json", - async:true, - success:function(json){ - var jid = json.releasededicatedpodresponse.jobid; - args.response.success({ - _custom: - { jobId: jid - }, - notification: { - poll: pollAsyncJobResult - }, - actionFilter:podActionfilter - - }); - }, - error:function(json){ - args.response.error(parseXMLHttpResponse(json)); + release:{ + label:'Release Dedicated Pod', + messages:{ + confirm: function(args) { + return 'Do you want to release this dedicated pod ?'; + }, + notification: function(args) { + return 'Pod dedication released'; } - }); - - } - }, + }, + action:function(args){ + $.ajax({ + url:createURL("releaseDedicatedPod&podid=" + args.context.pods[0].id), + dataType:"json", + async:true, + success:function(json){ + var jid = json.releasededicatedpodresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getActionFilter: function() { + return podActionfilter; + } + } + }); + }, + error:function(json){ + args.response.error(parseXMLHttpResponse(json)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, disable: { @@ -10550,116 +10542,111 @@ } }, - dedicate:{ - label: 'Dedicate Cluster', - messages: { - confirm: function(args) { - return 'Do you really want to dedicate this cluster to a domain/account? '; - }, - notification: function(args) { - return 'Cluster Dedicated'; - } + dedicate:{ + label: 'Dedicate Cluster', + messages: { + confirm: function(args) { + return 'Do you really want to dedicate this cluster to a domain/account? '; }, - createForm:{ - title:'Dedicate Cluster', - fields:{ - domainId:{ - label:'Domain', - validation:{required:true}, - select:function(args){ - $.ajax({ - url:createURL("listDomains&listAll=true"), - dataType:"json", - async:false, - success: function(json) { - var domainObjs= json.listdomainsresponse.domain; - var items=[]; - - $(domainObjs).each(function() { - items.push({id:this.id ,description:this.name }); - }); - - args.response.success({ - data: items - }); - } - - - }); - } - }, - - accountId:{ - label:'Account', - docID:'helpAccountForDedication', - validation:{required:false} - - } - - } - }, - action: function(args) { - //EXPLICIT DEDICATION - - var array2 = []; - if(args.data.accountId != "") - array2.push("&account=" +todb(args.data.accountId)); - - $.ajax({ - url: createURL("dedicateCluster&clusterId=" + args.context.clusters[0].id + "&domainId=" +args.data.domainId + array2.join("") ), - dataType: "json", - success: function(json) { - var jid = json.dedicateclusterresponse.jobid; - args.response.success({ - _custom: - { jobId: jid - }, - notification: { - poll: pollAsyncJobResult - }, - actionFilter:clusterActionfilter - }); - } - }); + notification: function(args) { + return 'Cluster Dedicated'; } - }, + createForm:{ + title:'Dedicate Cluster', + fields:{ + domainId:{ + label:'Domain', + validation:{required:true}, + select:function(args){ + $.ajax({ + url:createURL("listDomains&listAll=true"), + dataType:"json", + async:false, + success: function(json) { + var domainObjs= json.listdomainsresponse.domain; + var items=[]; - release:{ - label:'Release Dedicated Cluster', - messages:{ - confirm: function(args) { - return 'Do you want to release this dedicated cluster ?'; - }, - notification: function(args) { - return 'Cluster dedication released'; - } - }, - action:function(args){ - $.ajax({ - url:createURL("releaseDedicatedCluster&clusterid=" + args.context.clusters[0].id), - dataType:"json", - async:true, - success:function(json){ - var jid = json.releasededicatedclusterresponse.jobid; - args.response.success({ - _custom: - { jobId: jid - }, - notification: { - poll: pollAsyncJobResult - }, - actionFilter:clusterActionfilter + $(domainObjs).each(function() { + items.push({id:this.id ,description:this.name }); + }); - }); - }, - error:function(json){ - args.response.error(parseXMLHttpResponse(json)); + args.response.success({ + data: items + }); + } + }); } - }); - - } + }, + accountId:{ + label:'Account', + docID:'helpAccountForDedication', + validation:{required:false} + } + } }, + action: function(args) { + //EXPLICIT DEDICATION + var array2 = []; + if(args.data.accountId != "") + array2.push("&account=" +todb(args.data.accountId)); + $.ajax({ + url: createURL("dedicateCluster&clusterId=" + + args.context.clusters[0].id + + "&domainId=" +args.data.domainId + array2.join("") ), + dataType: "json", + success: function(json) { + var jid = json.dedicateclusterresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getActionFilter: function() { + return clusterActionfilter; + } + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, + release:{ + label:'Release Dedicated Cluster', + messages:{ + confirm: function(args) { + return 'Do you want to release this dedicated cluster ?'; + }, + notification: function(args) { + return 'Cluster dedication released'; + } + }, + action:function(args){ + $.ajax({ + url:createURL("releaseDedicatedCluster&clusterid=" + args.context.clusters[0].id), + dataType:"json", + async:true, + success:function(json){ + var jid = json.releasededicatedclusterresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getActionFilter: function() { + return clusterActionfilter; + } + } + }); + }, + error:function(json){ + args.response.error(parseXMLHttpResponse(json)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, manage: { @@ -11568,9 +11555,8 @@ } }, - - dedicate:{ - label: 'Dedicate Host', + dedicate:{ + label: 'Dedicate Host', messages: { confirm: function(args) { return 'Do you really want to dedicate this host to a domain/account? '; @@ -11580,107 +11566,101 @@ } }, createForm:{ - title:'Dedicate Host', - fields:{ - domainId:{ + title:'Dedicate Host', + fields:{ + domainId:{ label:'Domain', validation:{required:true}, select:function(args){ - $.ajax({ - url:createURL("listDomains&listAll=true"), - dataType:"json", - async:false, - success: function(json) { - var domainObjs= json.listdomainsresponse.domain; - var items=[]; - - $(domainObjs).each(function() { - items.push({id:this.id ,description:this.name }); - }); - - args.response.success({ - data: items - }); - } + $.ajax({ + url:createURL("listDomains&listAll=true"), + dataType:"json", + async:false, + success: function(json) { + var domainObjs= json.listdomainsresponse.domain; + var items=[]; + $(domainObjs).each(function() { + items.push({id:this.id ,description:this.name }); + }); + args.response.success({ + data: items + }); + } }); - } - }, - accountId:{ - label:'Account', - docID:'helpAccountForDedication', - validation:{required:false} - + } + }, + accountId:{ + label:'Account', + docID:'helpAccountForDedication', + validation:{required:false} + } } - - - } }, - action: function(args) { - //EXPLICIT DEDICATION - var array2 = []; - if(args.data.accountId != "") - array2.push("&account=" +todb(args.data.accountId)); + //EXPLICIT DEDICATION + var array2 = []; + if(args.data.accountId != "") + array2.push("&account=" +todb(args.data.accountId)); - $.ajax({ - url: createURL("dedicateHost&hostId=" + args.context.hosts[0].id + "&domainId=" +args.data.domainId + array2.join("") ), + $.ajax({ + url: createURL("dedicateHost&hostId=" + + args.context.hosts[0].id + + "&domainId=" +args.data.domainId + array2.join("")), dataType: "json", success: function(json) { - var jid = json.dedicatehostresponse.jobid; - args.response.success({ - _custom: - { jobId: jid - }, - notification: { - poll: pollAsyncJobResult - }, - actionFilter:hostActionfilter + var jid = json.dedicatehostresponse.jobid; - - }); + args.response.success({ + _custom: { + jobId: jid, + getActionFilter: function() { + return hostActionfilter; + } + } + }); } }); + }, + notification: { + poll: pollAsyncJobResult } - }, - - - release:{ + release:{ label:'Release Dedicated Host', messages:{ - confirm: function(args) { + confirm: function(args) { return 'Do you want to release this dedicated host ?'; }, notification: function(args) { return 'Host dedication released'; } }, - action:function(args){ + action:function(args){ $.ajax({ - url:createURL("releaseDedicatedHost&hostid=" + args.context.hosts[0].id), - dataType:"json", - async:true, - success:function(json){ - var jid = json.releasededicatedhostresponse.jobid; - args.response.success({ - _custom: - { jobId: jid - }, - notification: { - poll: pollAsyncJobResult - }, - actionFilter:hostActionfilter - - }); + url:createURL("releaseDedicatedHost&hostid=" + args.context.hosts[0].id), + dataType:"json", + async:true, + success:function(json){ + var jid = json.releasededicatedhostresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getActionFilter: function() { + return hostActionfilter; + } + } + }); }, error:function(json){ args.response.error(parseXMLHttpResponse(json)); } }); - - } + }, + notification: { + poll: pollAsyncJobResult + } }, From ac438a6d1dc21e58a6a376287147b7bcec4b327c Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 5 Jul 2013 09:49:56 +0200 Subject: [PATCH 16/23] CLOUDSTACK-3372: CapacityManager does not count destroyed volumes when deploy VMs --- server/src/com/cloud/capacity/CapacityManagerImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index 108de3bb077..101902c9b74 100755 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -501,8 +501,8 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, @Override public long getAllocatedPoolCapacity(StoragePoolVO pool, VMTemplateVO templateForVmCreation){ - // Get size for all the volumes - Pair sizes = _volumeDao.getCountAndTotalByPool(pool.getId()); + // Get size for all the non-destroyed volumes + Pair sizes = _volumeDao.getNonDestroyedCountAndTotalByPool(pool.getId()); long totalAllocatedSize = sizes.second() + sizes.first() * _extraBytesPerVolume; // Get size for VM Snapshots From f93c51e2bd86b321b2d5a7193a275f01739781a7 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 5 Jul 2013 10:02:29 +0200 Subject: [PATCH 17/23] CLOUDSTACK-3345: createLBStickinessPolicy replaces old stickiness policy if exists --- .../lb/LoadBalancingRulesManagerImpl.java | 42 ++++++++++--- ui/scripts/lbStickyPolicy.js | 63 +++++++++---------- 2 files changed, 62 insertions(+), 43 deletions(-) diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 470d9b850b1..6e0d0d77ed3 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -503,8 +503,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements /* Validation : check for the multiple policies to the rule id */ List stickinessPolicies = _lb2stickinesspoliciesDao.listByLoadBalancerId( cmd.getLbRuleId(), false); - if (stickinessPolicies.size() > 0) { - throw new InvalidParameterValueException("Failed to create Stickiness policy: Already policy attached " + if (stickinessPolicies.size() > 1) { + throw new InvalidParameterValueException("Failed to create Stickiness policy: Already two policies attached " + cmd.getLbRuleId()); } return true; @@ -651,14 +651,25 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements @ActionEvent(eventType = EventTypes.EVENT_LB_STICKINESSPOLICY_CREATE, eventDescription = "Apply Stickinesspolicy to load balancer ", async = true) public boolean applyLBStickinessPolicy(CreateLBStickinessPolicyCmd cmd) { boolean success = true; + FirewallRule.State backupState = null; + long oldStickinessPolicyId = 0; LoadBalancerVO loadBalancer = _lbDao.findById(cmd.getLbRuleId()); if (loadBalancer == null) { throw new InvalidParameterException("Invalid Load balancer Id:" + cmd.getLbRuleId()); } - FirewallRule.State backupState = loadBalancer.getState(); - loadBalancer.setState(FirewallRule.State.Add); - _lbDao.persist(loadBalancer); + List stickinessPolicies = _lb2stickinesspoliciesDao.listByLoadBalancerId(cmd.getLbRuleId(), false); + for (LBStickinessPolicyVO stickinessPolicy: stickinessPolicies) { + if (stickinessPolicy.getId() == cmd.getEntityId()) { + backupState = loadBalancer.getState(); + loadBalancer.setState(FirewallRule.State.Add); + _lbDao.persist(loadBalancer); + } else { + oldStickinessPolicyId = stickinessPolicy.getId(); + stickinessPolicy.setRevoke(true); + _lb2stickinesspoliciesDao.persist(stickinessPolicy); + } + } try { applyLoadBalancerConfig(cmd.getLbRuleId()); } catch (ResourceUnavailableException e) { @@ -667,10 +678,25 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (isRollBackAllowedForProvider(loadBalancer)) { loadBalancer.setState(backupState); _lbDao.persist(loadBalancer); + deleteLBStickinessPolicy(cmd.getEntityId(), false); s_logger.debug("LB Rollback rule id: " + loadBalancer.getId() + " lb state rolback while creating sticky policy"); + } else { + deleteLBStickinessPolicy(cmd.getEntityId(), false); + if (oldStickinessPolicyId != 0) { + LBStickinessPolicyVO stickinessPolicy = _lb2stickinesspoliciesDao.findById(oldStickinessPolicyId); + stickinessPolicy.setRevoke(false); + _lb2stickinesspoliciesDao.persist(stickinessPolicy); + try { + if (backupState.equals(FirewallRule.State.Active)) + applyLoadBalancerConfig(cmd.getLbRuleId()); + } catch (ResourceUnavailableException e1) { + } finally { + loadBalancer.setState(backupState); + _lbDao.persist(loadBalancer); + } + } } - deleteLBStickinessPolicy(cmd.getEntityId(), false); success = false; } @@ -759,7 +785,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements success = false; } } else { - _lb2stickinesspoliciesDao.remove(stickinessPolicy.getLoadBalancerId()); + _lb2stickinesspoliciesDao.expunge(stickinessPolicyId); } return success; } @@ -1690,7 +1716,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements @Override public List getStickinessPolicies(long lbId) { List stickinessPolicies = new ArrayList(); - List sDbpolicies = _lb2stickinesspoliciesDao.listByLoadBalancerId(lbId); + List sDbpolicies = _lb2stickinesspoliciesDao.listByLoadBalancerId(lbId, false); for (LBStickinessPolicyVO sDbPolicy : sDbpolicies) { LbStickinessPolicy sPolicy = new LbStickinessPolicy(sDbPolicy.getMethodName(), sDbPolicy.getParams(), diff --git a/ui/scripts/lbStickyPolicy.js b/ui/scripts/lbStickyPolicy.js index 2d132dab57b..02ebabea77a 100644 --- a/ui/scripts/lbStickyPolicy.js +++ b/ui/scripts/lbStickyPolicy.js @@ -259,6 +259,32 @@ } }); }, + delete: function(stickyRuleID, complete, error) { + $.ajax({ + url: createURL('deleteLBStickinessPolicy'), + data: { + id: stickyRuleID + }, + success: function(json) { + cloudStack.ui.notifications.add( + { + desc: 'Remove previous LB sticky rule', + section: 'Network', + poll: pollAsyncJobResult, + _custom: { + jobId: json.deleteLBstickinessrruleresponse.jobid + } + }, + complete, {}, + error, {} + ); + }, + error: function(json) { + complete(); + cloudStack.dialog.notice({ message: parseXMLHttpResponse(json) }); + } + }); + }, recreate: function(stickyRuleID, lbRuleID, data, complete, error) { var addStickyPolicy = function() { cloudStack.lbStickyPolicy.actions.add( @@ -270,43 +296,10 @@ }; // Delete existing rule - if (stickyRuleID) { - $.ajax({ - url: createURL('deleteLBStickinessPolicy'), - data: { - id: stickyRuleID - }, - success: function(json) { - cloudStack.ui.notifications.add( - { - desc: 'Remove previous LB sticky rule', - section: 'Network', - poll: pollAsyncJobResult, - _custom: { - jobId: json.deleteLBstickinessrruleresponse.jobid - } - }, - function() { - if (data.methodname != 'None') { - addStickyPolicy(); - } else { - complete(); - } - }, {}, - error, {} - ); - }, - error: function(json) { - cloudStack.dialog.notice({ - message: parseXMLHttpResponse(json) - }); - error(); - } - }); - } else if (data.methodname != 'None') { + if (data.methodname != 'None') { addStickyPolicy(); } else { - complete(); + cloudStack.lbStickyPolicy.actions.delete(stickyRuleID, complete, error); } } } From e173060ab647052c47310f73eddc10a199cc148d Mon Sep 17 00:00:00 2001 From: Radhika PC Date: Fri, 5 Jul 2013 14:00:04 +0530 Subject: [PATCH 18/23] CLOUDSTACK-2762 --- docs/en-US/add-vm-tier-sharednw.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/en-US/add-vm-tier-sharednw.xml b/docs/en-US/add-vm-tier-sharednw.xml index e1a37c8895c..94121f24103 100644 --- a/docs/en-US/add-vm-tier-sharednw.xml +++ b/docs/en-US/add-vm-tier-sharednw.xml @@ -19,7 +19,10 @@ under the License. -->
- Deploying VMs to a Tier and Shared Network + Deploying VMs to VPC Tier and Shared Networks + &PRODUCT; allows you deploy VMs on a VPC tier and one or more shared networks. With this + feature, VMs deployed in a multi-tier application can receive monitoring services via a shared + network provided by a service provider. Log in to the &PRODUCT; UI as an administrator or end user. From 6efd337ef422d3c5b2a14bb27bee9738dd3e42ae Mon Sep 17 00:00:00 2001 From: Radhika PC Date: Fri, 5 Jul 2013 14:46:10 +0530 Subject: [PATCH 19/23] CLOUDSTACK-2762 --- docs/en-US/add-vm-tier-sharednw.xml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/en-US/add-vm-tier-sharednw.xml b/docs/en-US/add-vm-tier-sharednw.xml index 94121f24103..411b943e35d 100644 --- a/docs/en-US/add-vm-tier-sharednw.xml +++ b/docs/en-US/add-vm-tier-sharednw.xml @@ -25,14 +25,11 @@ network provided by a service provider. - Log in to the &PRODUCT; UI as an administrator or end user. + Log in to the &PRODUCT; UI as an administrator. In the left navigation, choose Instances. - - Select the VM you want to work with. - Click Add Instance. @@ -41,8 +38,6 @@ Select a template or ISO, then follow the steps in the wizard. - For more information about how the templates came to be in this list, see . Ensure that the hardware you have allows starting the selected service offering. From 88f67c128c73bd40d96c3ef15306cb9cbacb9632 Mon Sep 17 00:00:00 2001 From: Sebastien Goasguen Date: Fri, 5 Jul 2013 05:21:24 -0400 Subject: [PATCH 20/23] [DOCS][GSOC] re-formatted GSoC guide for updates --- docs/en-US/CloudStack_GSoC_Guide.xml | 7 ++---- docs/en-US/gsoc-dharmesh.xml | 4 +-- docs/en-US/gsoc-imduffy15.xml | 4 +-- docs/en-US/gsoc-meng.xml | 4 +-- docs/en-US/gsoc-midsummer-dharmesh.xml | 28 +++++++++++++++++++++ docs/en-US/gsoc-midsummer-ian.xml | 28 +++++++++++++++++++++ docs/en-US/gsoc-midsummer-meng.xml | 28 +++++++++++++++++++++ docs/en-US/gsoc-midsummer-nguyen.xml | 28 +++++++++++++++++++++ docs/en-US/gsoc-midsummer-shiva.xml | 28 +++++++++++++++++++++ docs/en-US/gsoc-midsummer.xml | 35 ++++++++++++++++++++++++++ docs/en-US/gsoc-proposals.xml | 35 ++++++++++++++++++++++++++ docs/en-US/gsoc-shiva.xml | 4 +-- docs/en-US/gsoc-tuna.xml | 4 +-- 13 files changed, 222 insertions(+), 15 deletions(-) create mode 100644 docs/en-US/gsoc-midsummer-dharmesh.xml create mode 100644 docs/en-US/gsoc-midsummer-ian.xml create mode 100644 docs/en-US/gsoc-midsummer-meng.xml create mode 100644 docs/en-US/gsoc-midsummer-nguyen.xml create mode 100644 docs/en-US/gsoc-midsummer-shiva.xml create mode 100644 docs/en-US/gsoc-midsummer.xml create mode 100644 docs/en-US/gsoc-proposals.xml diff --git a/docs/en-US/CloudStack_GSoC_Guide.xml b/docs/en-US/CloudStack_GSoC_Guide.xml index cd8205d34ba..2f537d40cef 100644 --- a/docs/en-US/CloudStack_GSoC_Guide.xml +++ b/docs/en-US/CloudStack_GSoC_Guide.xml @@ -46,10 +46,7 @@ - - - - - + + diff --git a/docs/en-US/gsoc-dharmesh.xml b/docs/en-US/gsoc-dharmesh.xml index 5e2bf734d7f..01a77c70ab0 100644 --- a/docs/en-US/gsoc-dharmesh.xml +++ b/docs/en-US/gsoc-dharmesh.xml @@ -22,7 +22,7 @@ under the License. --> - +
Dharmesh's 2013 GSoC Proposal This chapter describes Dharmrsh's 2013 Google Summer of Code project within the &PRODUCT; ASF project. It is a copy paste of the submitted proposal.
@@ -146,4 +146,4 @@
- +
diff --git a/docs/en-US/gsoc-imduffy15.xml b/docs/en-US/gsoc-imduffy15.xml index 652152fcc4b..f78cb540704 100644 --- a/docs/en-US/gsoc-imduffy15.xml +++ b/docs/en-US/gsoc-imduffy15.xml @@ -22,7 +22,7 @@ under the License. --> - +
Ians's 2013 GSoC Proposal This chapter describes Ians 2013 Google Summer of Code project within the &PRODUCT; ASF project. It is a copy paste of the submitted proposal.
@@ -392,4 +392,4 @@ cool. I’m excited at the opportunity and learning experience that cloudstack are offering with this project.
- +
diff --git a/docs/en-US/gsoc-meng.xml b/docs/en-US/gsoc-meng.xml index 1de259dcac1..8ea2b4cfda7 100644 --- a/docs/en-US/gsoc-meng.xml +++ b/docs/en-US/gsoc-meng.xml @@ -22,7 +22,7 @@ under the License. --> - +
Meng's 2013 GSoC Proposal This chapter describes Meng's 2013 Google Summer of Code project within the &PRODUCT; ASF project. It is a copy paste of the submitted proposal.
@@ -232,4 +232,4 @@ http://chriskleban-internet.blogspot.com/2012/03/build-cloud-cloudstack-instance
- +
diff --git a/docs/en-US/gsoc-midsummer-dharmesh.xml b/docs/en-US/gsoc-midsummer-dharmesh.xml new file mode 100644 index 00000000000..69e417aeac5 --- /dev/null +++ b/docs/en-US/gsoc-midsummer-dharmesh.xml @@ -0,0 +1,28 @@ + + +%BOOK_ENTITIES; +]> + + + +
+ Mid-Summer Progress Updates + This section describes ... +
diff --git a/docs/en-US/gsoc-midsummer-ian.xml b/docs/en-US/gsoc-midsummer-ian.xml new file mode 100644 index 00000000000..348418f6969 --- /dev/null +++ b/docs/en-US/gsoc-midsummer-ian.xml @@ -0,0 +1,28 @@ + + +%BOOK_ENTITIES; +]> + + + +
+ Mid-Summer Progress Updates + This section describes ... +
diff --git a/docs/en-US/gsoc-midsummer-meng.xml b/docs/en-US/gsoc-midsummer-meng.xml new file mode 100644 index 00000000000..1ab07cb93b8 --- /dev/null +++ b/docs/en-US/gsoc-midsummer-meng.xml @@ -0,0 +1,28 @@ + + +%BOOK_ENTITIES; +]> + + + +
+ Mid-Summer Progress Updates + This section describes ... +
diff --git a/docs/en-US/gsoc-midsummer-nguyen.xml b/docs/en-US/gsoc-midsummer-nguyen.xml new file mode 100644 index 00000000000..96c2de10259 --- /dev/null +++ b/docs/en-US/gsoc-midsummer-nguyen.xml @@ -0,0 +1,28 @@ + + +%BOOK_ENTITIES; +]> + + + +
+ Mid-Summer Progress Updates + This section describes ... +
diff --git a/docs/en-US/gsoc-midsummer-shiva.xml b/docs/en-US/gsoc-midsummer-shiva.xml new file mode 100644 index 00000000000..67755c46eb1 --- /dev/null +++ b/docs/en-US/gsoc-midsummer-shiva.xml @@ -0,0 +1,28 @@ + + +%BOOK_ENTITIES; +]> + + + +
+ Mid-Summer Progress Updates + This section describes ... +
diff --git a/docs/en-US/gsoc-midsummer.xml b/docs/en-US/gsoc-midsummer.xml new file mode 100644 index 00000000000..ffb031a90c7 --- /dev/null +++ b/docs/en-US/gsoc-midsummer.xml @@ -0,0 +1,35 @@ + + +%BOOK_ENTITIES; +]> + + + + + Mid-Summer Progress Updates + This chapter describes the progress of each &PRODUCT; Google Summer of Code project. + + + + + + + + diff --git a/docs/en-US/gsoc-proposals.xml b/docs/en-US/gsoc-proposals.xml new file mode 100644 index 00000000000..7c4b50c6511 --- /dev/null +++ b/docs/en-US/gsoc-proposals.xml @@ -0,0 +1,35 @@ + + +%BOOK_ENTITIES; +]> + + + + + Google Summer of Code Proposals + This chapter contains the five proposals awarded to &PRODUCT; for the 2013 Google Summer of Code project. + + + + + + + + diff --git a/docs/en-US/gsoc-shiva.xml b/docs/en-US/gsoc-shiva.xml index 400af3c82f6..fe36d8ef050 100644 --- a/docs/en-US/gsoc-shiva.xml +++ b/docs/en-US/gsoc-shiva.xml @@ -22,7 +22,7 @@ under the License. --> - +
Shiva Teja's 2013 GSoC Proposal This chapter describes Shiva Teja's 2013 Google Summer of Code project within the &PRODUCT; ASF project. It is a copy paste of the submitted proposal.
@@ -67,4 +67,4 @@ About Me I am a 2nd year computer science undergrad studying at IIT Mandi, India. I've been using Python for an year and a half now. I've used Django, Flask and Tornado for my small projects. Along with Python, I use C++ for competitive programming. Recently, I fell in love with Haskell. I've always been fascinated about web technologies.
- +
diff --git a/docs/en-US/gsoc-tuna.xml b/docs/en-US/gsoc-tuna.xml index 0988734a465..aa9726f095c 100644 --- a/docs/en-US/gsoc-tuna.xml +++ b/docs/en-US/gsoc-tuna.xml @@ -22,7 +22,7 @@ under the License. --> - +
Nguyen's 2013 GSoC Proposal This chapter describes Nguyen 2013 Google Summer of Code project within the &PRODUCT; ASF project. It is a copy paste of the submitted proposal.
@@ -228,4 +228,4 @@
- +
From f96b89f25e59a92b4e92a07fc54c8e6a9177b6c7 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 5 Jul 2013 15:31:26 +0530 Subject: [PATCH 21/23] CLOUDSTACK-3273: ClassCastException when adding cache store via API Filter the detail map sent over the wire into Map before processing underneath by storage life cycle Signed-off-by: Prasanna Santhanam --- .../admin/storage/CreateCacheStoreCmd.java | 26 ++++++++++++++----- .../image/datastore/ImageStoreHelper.java | 2 +- tools/marvin/marvin/integration/lib/utils.py | 8 ++---- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/CreateCacheStoreCmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/CreateCacheStoreCmd.java index ff01a40c1fa..f94207fda91 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/storage/CreateCacheStoreCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/storage/CreateCacheStoreCmd.java @@ -18,22 +18,22 @@ */ package org.apache.cloudstack.api.command.admin.storage; -import java.util.Map; - +import com.cloud.storage.ImageStore; +import com.cloud.user.Account; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.BaseCmd.CommandType; import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.log4j.Logger; -import com.cloud.exception.DiscoveryException; -import com.cloud.storage.ImageStore; -import com.cloud.user.Account; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; @APICommand(name = "createCacheStore", description="create cache store.", responseObject=ImageStoreResponse.class) public class CreateCacheStoreCmd extends BaseCmd { @@ -76,7 +76,19 @@ public class CreateCacheStoreCmd extends BaseCmd { } public Map getDetails() { - return details; + Map detailsMap = null; + if (details != null && !details.isEmpty()) { + detailsMap = new HashMap(); + Collection props = details.values(); + Iterator iter = props.iterator(); + while (iter.hasNext()) { + HashMap detail = (HashMap) iter.next(); + String key = detail.get("key"); + String value = detail.get("value"); + detailsMap.put(key, value); + } + } + return detailsMap; } public String getScope() { diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java index a2d61f91fbe..a64114691c8 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java @@ -95,7 +95,7 @@ public class ImageStoreHelper { if (details != null) { Iterator keyIter = details.keySet().iterator(); while (keyIter.hasNext()) { - String key = keyIter.next(); + String key = keyIter.next().toString(); ImageStoreDetailVO detail = new ImageStoreDetailVO(); detail.setStoreId(store.getId()); detail.setName(key); diff --git a/tools/marvin/marvin/integration/lib/utils.py b/tools/marvin/marvin/integration/lib/utils.py index 9ab199ab7d4..4eca8baab20 100644 --- a/tools/marvin/marvin/integration/lib/utils.py +++ b/tools/marvin/marvin/integration/lib/utils.py @@ -185,16 +185,12 @@ def get_process_status(hostip, port, username, password, linklocalip, process, h return res -def isAlmostEqual(self, first_digit, second_digit, range=0): +def isAlmostEqual(first_digit, second_digit, range=0): digits_equal_within_range = False try: if ((first_digit - range) < second_digit < (first_digit + range)): digits_equal_within_range = True - except Exception as e: - self.fail( - "%s: Failed while comparing the numbers %s & %s" % - (e, first_digit, second_digit)) - + raise e return digits_equal_within_range From 0d7d345339a9b3c034de9b979c3a33a3301cb8e5 Mon Sep 17 00:00:00 2001 From: Isaac Chiang Date: Fri, 5 Jul 2013 18:21:34 +0800 Subject: [PATCH 22/23] CLOUDSTACK-3230: UI add cluster remains in processing state --- ui/scripts/system.js | 48 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 70b4f8d6195..dd971edbb5f 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -10373,36 +10373,36 @@ //EXPLICIT DEDICATION var array2 = []; - if(args.$form.find('.form-item[rel=isDedicated]').find('input[type=checkbox]').is(':Checked')== true){ + if(args.$form.find('.form-item[rel=isDedicated]').find('input[type=checkbox]').is(':Checked')== true) { if(args.data.accountId != "") array2.push("&account=" +todb(args.data.accountId)); + if(clusterId != null){ + $.ajax({ + url:createURL("dedicateCluster&clusterId=" +clusterId +"&domainId=" +args.data.domainId + array2.join("")), + dataType:"json", + success:function(json){ + var jid = json.dedicateclusterresponse.jobid; + args.response.success({ + _custom: + { jobId: jid + }, + notification: { + poll: pollAsyncJobResult + }, - if(clusterId != null){ - $.ajax({ - url:createURL("dedicateCluster&clusterId=" +clusterId +"&domainId=" +args.data.domainId + array2.join("")), - dataType:"json", - success:function(json){ - var jid = json.dedicateclusterresponse.jobid; - args.response.success({ - _custom: - { jobId: jid - }, - notification: { - poll: pollAsyncJobResult - }, + data:$.extend(item, {state:'Enabled'}) + }); - data:$.extend(item, {state:'Enabled'}) - }); - - }, - - error:function(json){ - args.response.error(parseXMLHttpResponse(XMLHttpResponse)); - } - }); + }, + error:function(json){ + args.response.error(parseXMLHttpResponse(XMLHttpResponse)); + } + }); + } + } else { + args.response.success({data: item}); } - } }, error: function(XMLHttpResponse) { var errorMsg = parseXMLHttpResponse(XMLHttpResponse); From c56a75da9c0c38dc1d9d5fbaa4ba21371d3d17d6 Mon Sep 17 00:00:00 2001 From: Radhika PC Date: Fri, 5 Jul 2013 16:07:04 +0530 Subject: [PATCH 23/23] CLOUDSTACK-2763 --- docs/en-US/add-loadbalancer-rule-vpc.xml | 317 +++++++++++++++-------- docs/en-US/add-vm-tier-sharednw.xml | 2 +- docs/en-US/add-vpc.xml | 7 +- docs/en-US/images/add-vpc.png | Bin 16597 -> 20392 bytes 4 files changed, 217 insertions(+), 109 deletions(-) diff --git a/docs/en-US/add-loadbalancer-rule-vpc.xml b/docs/en-US/add-loadbalancer-rule-vpc.xml index 82e870243d1..0f2a83dcbfd 100644 --- a/docs/en-US/add-loadbalancer-rule-vpc.xml +++ b/docs/en-US/add-loadbalancer-rule-vpc.xml @@ -35,113 +35,216 @@ received at a public IP to one or more VMs that belong to a network tier that provides load balancing service in a VPC. A user creates a rule, specifies an algorithm, and assigns the rule to a set of VMs within a tier. - - - Log in to the &PRODUCT; UI as an administrator or end user. - - - In the left navigation, choose Network. - - - In the Select view, select VPC. - All the VPCs that you have created for the account is listed in the page. - - - Click the Configure button of the VPC, for which you want to configure load balancing - rules. - The VPC page is displayed where all the tiers you created listed in a diagram. - For each tier, the following options are displayed: - - - Internal LB - - - Public LB IP - - - Static NAT - - - Virtual Machines - - - CIDR - - - The following router information is displayed: - - - Private Gateways - - - Public IP Addresses - - - Site-to-Site VPNs - - - Network ACL Lists - - - - - In the Router node, select Public IP Addresses. - The IP Addresses page is displayed. - - - Click the IP address for which you want to create the rule, then click the - Configuration tab. - - - In the Load Balancing node of the diagram, click View All. - - - Select the tier to which you want to apply the rule. - - - Specify the following: - - - Name: A name for the load balancer rule. - - - Public Port: The port that receives the incoming - traffic to be balanced. - - - Private Port: The port that the VMs will use to - receive the traffic. - - - Algorithm. Choose the load balancing algorithm - you want &PRODUCT; to use. &PRODUCT; supports the following well-known - algorithms: - - - Round-robin - - - Least connections - - - Source - - - - - Stickiness. (Optional) Click Configure and choose - the algorithm for the stickiness policy. See Sticky Session Policies for Load Balancer - Rules. - - - Add VMs: Click Add VMs, then select two or more - VMs that will divide the load of incoming traffic, and click Apply. - - - - - The new load balancing rule appears in the list. You can repeat these steps to add more - load balancing rules for this IP address. +
+ Enabling NetScaler as the LB Provider on a VPC Tier + + + Add and enable Netscaler VPX in dedicated mode. + Netscaler can be used in a VPC environment only if it is in dedicated mode. + + + Create a network offering, as given in . + + + Create a VPC with Netscaler as the Public LB provider. + For more information, see . + + + For the VPC, acquire an IP. + + + Create an external load balancing rule and apply, as given in . + + +
+
+ Creating a Network Offering for External LB + To have internal LB support on VPC, create a network offering as follows: + + + Log in to the &PRODUCT; UI as a user or admin. + + + From the Select Offering drop-down, choose Network Offering. + + + Click Add Network Offering. + + + In the dialog, make the following choices: + + + Name: Any desired name for the network + offering. + + + Description: A short description of the + offering that can be displayed to users. + + + Network Rate: Allowed data transfer rate in MB + per second. + + + Traffic Type: The type of network traffic that + will be carried on the network. + + + Guest Type: Choose whether the guest network is + isolated or shared. + + + Persistent: Indicate whether the guest network + is persistent or not. The network that you can provision without having to deploy a + VM on it is termed persistent network. + + + VPC: This option indicate whether the guest + network is Virtual Private Cloud-enabled. A Virtual Private Cloud (VPC) is a + private, isolated part of &PRODUCT;. A VPC can have its own virtual network topology + that resembles a traditional physical network. For more information on VPCs, see + . + + + Specify VLAN: (Isolated guest networks only) + Indicate whether a VLAN should be specified when this offering is used. + + + Supported Services: Select Load Balancer. + Select InternalLbVM from the provider list. + + + Load Balancer Type: Select external LB from the + drop-down. Use Netscaler + + + System Offering: Choose the system service + offering that you want virtual routers to use in this network. + + + Conserve mode: Indicate whether to use conserve + mode. In this mode, network resources are allocated only when the first virtual + machine starts in the network. + + + + + Click OK and the network offering is created. + + +
+
+ Creating an External LB Rule + + + Log in to the &PRODUCT; UI as an administrator or end user. + + + In the left navigation, choose Network. + + + In the Select view, select VPC. + All the VPCs that you have created for the account is listed in the page. + + + Click the Configure button of the VPC, for which you want to configure load + balancing rules. + The VPC page is displayed where all the tiers you created listed in a + diagram. + For each tier, the following options are displayed: + + + Internal LB + + + Public LB IP + + + Static NAT + + + Virtual Machines + + + CIDR + + + The following router information is displayed: + + + Private Gateways + + + Public IP Addresses + + + Site-to-Site VPNs + + + Network ACL Lists + + + + + In the Router node, select Public IP Addresses. + The IP Addresses page is displayed. + + + Click the IP address for which you want to create the rule, then click the + Configuration tab. + + + In the Load Balancing node of the diagram, click View All. + + + Select the tier to which you want to apply the rule. + + + Specify the following: + + + Name: A name for the load balancer rule. + + + Public Port: The port that receives the + incoming traffic to be balanced. + + + Private Port: The port that the VMs will use to + receive the traffic. + + + Algorithm. Choose the load balancing algorithm + you want &PRODUCT; to use. &PRODUCT; supports the following well-known + algorithms: + + + Round-robin + + + Least connections + + + Source + + + + + Stickiness. (Optional) Click Configure and + choose the algorithm for the stickiness policy. See Sticky Session Policies for Load + Balancer Rules. + + + Add VMs: Click Add VMs, then select two or more + VMs that will divide the load of incoming traffic, and click Apply. + + + + + The new load balancing rule appears in the list. You can repeat these steps to add more + load balancing rules for this IP address. +
Load Balancing Across Tiers diff --git a/docs/en-US/add-vm-tier-sharednw.xml b/docs/en-US/add-vm-tier-sharednw.xml index 411b943e35d..a68860419eb 100644 --- a/docs/en-US/add-vm-tier-sharednw.xml +++ b/docs/en-US/add-vm-tier-sharednw.xml @@ -43,7 +43,7 @@ Ensure that the hardware you have allows starting the selected service offering. - Under Networks, select networks for the VM you are launching. + Under Networks, select the desired networks for the VM you are launching. You can deploy a VM to a VPC tier and multiple shared networks. diff --git a/docs/en-US/add-vpc.xml b/docs/en-US/add-vpc.xml index 8c088a0e1fd..b8034c4b4c8 100644 --- a/docs/en-US/add-vpc.xml +++ b/docs/en-US/add-vpc.xml @@ -67,9 +67,14 @@ assign a special domain name, specify the DNS suffix. This parameter is applied to all the tiers within the VPC. That implies, all the tiers you create in the VPC belong to the same DNS domain. If the parameter is not specified, a DNS domain name is generated - automatically. + automatically. + + + Public Load Balancer Provider: You have two + options: VPC Virtual Router and Netscaler. + Click OK.
diff --git a/docs/en-US/images/add-vpc.png b/docs/en-US/images/add-vpc.png index 6b9c6379d9ff64e4ae5b26a00215e5a8850c995e..f3348623416ab56654377270dc645f1f6d473d81 100644 GIT binary patch literal 20392 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 X>#hNg(P}_-JsLyZ%Q_`mwh#UTF>2^J literal 16597 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 OAS0>xzT%xx@c#n);>q>^