Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E16E711D1B for ; Mon, 28 Jul 2014 21:13:46 +0000 (UTC) Received: (qmail 81615 invoked by uid 500); 28 Jul 2014 21:13:31 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 81568 invoked by uid 500); 28 Jul 2014 21:13:31 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 80527 invoked by uid 99); 28 Jul 2014 21:13:30 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 28 Jul 2014 21:13:30 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 3E69D9B8A72; Mon, 28 Jul 2014 21:13:30 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: dahn@apache.org To: commits@cloudstack.apache.org Date: Mon, 28 Jul 2014 21:14:11 -0000 Message-Id: <5fe38c5e5cba471b977445b0ae45d2e9@git.apache.org> In-Reply-To: <294c500168744efe89e6fc45a6409bfa@git.apache.org> References: <294c500168744efe89e6fc45a6409bfa@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [43/50] [abbrv] git commit: updated refs/heads/4.4 to 2025f35 Added a simulator based test for VM sync (cherry picked from commit a83212afdc5558582d2aa60727bb28648472d95d) Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/e1cfd8de Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/e1cfd8de Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/e1cfd8de Branch: refs/heads/4.4 Commit: e1cfd8dedf03a7b10ad4dd5246e6dcded444cef3 Parents: 999daec Author: Koushik Das Authored: Mon Jul 7 12:53:05 2014 +0530 Committer: Daan Hoogland Committed: Mon Jul 28 23:12:55 2014 +0200 ---------------------------------------------------------------------- .../api/commands/ConfigureSimulatorCmd.java | 5 +- .../cloud/simulator/MockConfigurationVO.java | 2 +- test/integration/smoke/test_vm_sync.py | 151 +++++++++++++++++++ tools/marvin/marvin/config/test_data.py | 22 ++- tools/marvin/marvin/lib/base.py | 4 +- 5 files changed, 173 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e1cfd8de/plugins/hypervisors/simulator/src/com/cloud/api/commands/ConfigureSimulatorCmd.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/simulator/src/com/cloud/api/commands/ConfigureSimulatorCmd.java b/plugins/hypervisors/simulator/src/com/cloud/api/commands/ConfigureSimulatorCmd.java index 9498a93..b891c6c 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/api/commands/ConfigureSimulatorCmd.java +++ b/plugins/hypervisors/simulator/src/com/cloud/api/commands/ConfigureSimulatorCmd.java @@ -69,12 +69,15 @@ public class ConfigureSimulatorCmd extends BaseCmd { @Parameter(name=ApiConstants.COUNT, type=CommandType.INTEGER, description="number of times the mock is active") private Integer count; - @Parameter(name="jsonresponse", type=CommandType.STRING, description="agent command response to be returned") + @Parameter(name="jsonresponse", type=CommandType.STRING, description="agent command response to be returned", length=4096) private String jsonResponse; @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + if (hostId != null && jsonResponse != null) { + jsonResponse = jsonResponse.replace("\"hostId\":0", "\"hostId\":" + hostId); + } Long id = _simMgr.configureSimulator(zoneId, podId, clusterId, hostId, command, values, count, jsonResponse); if (id == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to configure simulator"); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e1cfd8de/plugins/hypervisors/simulator/src/com/cloud/simulator/MockConfigurationVO.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/simulator/src/com/cloud/simulator/MockConfigurationVO.java b/plugins/hypervisors/simulator/src/com/cloud/simulator/MockConfigurationVO.java index 1beff76..6edec12 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/simulator/MockConfigurationVO.java +++ b/plugins/hypervisors/simulator/src/com/cloud/simulator/MockConfigurationVO.java @@ -60,7 +60,7 @@ public class MockConfigurationVO implements InternalIdentity { @Column(name="count") private Integer count; - @Column(name="json_response") + @Column(name="json_response", length=4096) private String jsonResponse; @Column(name="removed") http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e1cfd8de/test/integration/smoke/test_vm_sync.py ---------------------------------------------------------------------- diff --git a/test/integration/smoke/test_vm_sync.py b/test/integration/smoke/test_vm_sync.py new file mode 100644 index 0000000..6d56945 --- /dev/null +++ b/test/integration/smoke/test_vm_sync.py @@ -0,0 +1,151 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +#Test from the Marvin - Testing in Python wiki + +import time + +#All tests inherit from cloudstackTestCase +from marvin.cloudstackTestCase import cloudstackTestCase + +#Import Integration Libraries + +#base - contains all resources as entities and defines create, delete, list operations on them +from marvin.lib.base import Account, VirtualMachine, Cluster, Host, ServiceOffering, Configurations, SimulatorMock + +#utils - utility classes for common cleanup, external library wrappers etc +from marvin.lib.utils import cleanup_resources + +#common - commonly used methods for all tests are listed here +from marvin.lib.common import get_zone, get_domain, get_template + +from nose.plugins.attrib import attr + +class TestDeployVMSync(cloudstackTestCase): + """Test VM Sync + """ + + def setUp(self): + self.testdata = self.testClient.getParsedTestDataConfig() + self.apiclient = self.testClient.getApiClient() + + # Get Zone, Domain and Default Built-in template + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + + self.testdata["mode"] = self.zone.networktype + self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"]) + + hosts = Host.list(self.apiclient, type='Routing') + self.assertTrue(isinstance(hosts, list) and len(hosts) > 0, msg = "No hosts found") + self.host = hosts[0] + #update host tags + Host.update(self.apiclient, id=self.host.id, hosttags=self.testdata["service_offerings"]["taggedsmall"]["hosttags"]) + + #create a user account + self.account = Account.create( + self.apiclient, + self.testdata["account"], + domainid=self.domain.id + ) + #create a service offering + self.service_offering = ServiceOffering.create( + self.apiclient, + self.testdata["service_offerings"]["taggedsmall"] + ) + #deploy vms + self.vm1 = VirtualMachine.create( + self.apiclient, + self.testdata["small"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id + ) + self.vm2 = VirtualMachine.create( + self.apiclient, + self.testdata["small"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id + ) + self.vm3 = VirtualMachine.create( + self.apiclient, + self.testdata["small"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id + ) + list_vms = VirtualMachine.list(self.apiclient, ids=[self.vm1.id, self.vm2.id, self.vm3.id], listAll=True) + self.assertTrue(isinstance(list_vms, list) and len(list_vms) == 3, msg = "List VM response is empty") + clusters = Cluster.list(self.apiclient, id=self.host.clusterid) + self.assertTrue(isinstance(clusters, list) and len(clusters) > 0, msg = "Cluster not found") + + json_response = '{"com.cloud.agent.api.PingRoutingWithNwGroupsCommand":{"newGroupStates":{},"newStates":{},"_hostVmStateReport":{"%s":{"state":"PowerOn","host":"%s"},"%s":{"state":"PowerOff","host":"%s"}},"_gatewayAccessible":true,"_vnetAccessible":true,"hostType":"Routing","hostId":0,"contextMap":{},"wait":0}}' + json_response = json_response%(self.vm1.instancename, self.host.name, self.vm2.instancename, self.host.name) + + #create a mock to simulate vm1 as power-on, vm2 as power-off and vm3 as missing + self.mock_ping = SimulatorMock.create( + apiclient=self.apiclient, + command="PingRoutingWithNwGroupsCommand", + zoneid=self.zone.id, + podid=clusters[0].podid, + clusterid=clusters[0].id, + hostid=self.host.id, + value='', + jsonresponse=json_response, + method='POST') + + #build cleanup list + self.cleanup = [ + self.service_offering, + self.account, + self.mock_ping + ] + + @attr(tags = ['advanced'], required_hardware="false", BugId="CLOUDSTACK-6873") + def test_vm_sync(self): + """Test VM Sync + + # Validate the following: + # vm1 should be running, vm2 should be stopped as power report says PowerOff, vm3 should be stopped as missing from power report + """ + + #wait for vmsync to happen + ping_interval = Configurations.list(self.apiclient, name="ping.interval") + total_duration = int(float(ping_interval[0].value) * 3.2) + time.sleep(total_duration) + + list_vms = VirtualMachine.list(self.apiclient, ids=[self.vm1.id, self.vm2.id, self.vm3.id], listAll=True) + self.assertTrue(isinstance(list_vms, list) and len(list_vms) == 3, msg = "List VM response is empty") + for vm in list_vms: + if vm.id == self.vm1.id: + self.assertTrue(vm.state == "Running", msg = "VM {0} is expected to be in running state".format(vm.name)) + elif vm.id == self.vm2.id or vm.id == self.vm3.id: + self.assertTrue(vm.state == "Stopped", msg = "VM {0} is expected to be in stopped state".format(vm.name)) + + def tearDown(self): + try: + Host.update(self.apiclient, id=self.host.id, hosttags="") + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e1cfd8de/tools/marvin/marvin/config/test_data.py ---------------------------------------------------------------------- diff --git a/tools/marvin/marvin/config/test_data.py b/tools/marvin/marvin/config/test_data.py index 61c1338..3cd4b6c 100644 --- a/tools/marvin/marvin/config/test_data.py +++ b/tools/marvin/marvin/config/test_data.py @@ -91,7 +91,7 @@ test_data = { "memory": 128, "tiny": { - "name": "Tiny Instance", + "name": "Tiny Instance", "displaytext": "Tiny Instance", "cpunumber": 1, "cpuspeed": 100, @@ -120,12 +120,20 @@ test_data = { }, "hasmall": { "name": "HA Small Instance", - "displaytext": "HA Small Instance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - "hosttags": "ha", - "offerha": True, + "displaytext": "HA Small Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + "hosttags": "ha", + "offerha": True, + }, + "taggedsmall": { + "name": "Tagged Small Instance", + "displaytext": "Tagged Small Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + "hosttags": "vmsync", }, }, "disk_offering": { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e1cfd8de/tools/marvin/marvin/lib/base.py ---------------------------------------------------------------------- diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py index b216bca..ff75176 100644 --- a/tools/marvin/marvin/lib/base.py +++ b/tools/marvin/marvin/lib/base.py @@ -4656,7 +4656,7 @@ class SimulatorMock: @classmethod def create(cls, apiclient, command, zoneid=None, podid=None, clusterid=None, hostid=None, value="result:fail", - count=None, jsonresponse=None): + count=None, jsonresponse=None, method="GET"): """Creates simulator mock""" cmd = configureSimulator.configureSimulatorCmd() @@ -4669,7 +4669,7 @@ class SimulatorMock: cmd.count = count cmd.jsonresponse = jsonresponse try: - simulatormock = apiclient.configureSimulator(cmd) + simulatormock = apiclient.configureSimulator(cmd, method=method) if simulatormock is not None: return SimulatorMock(simulatormock.__dict__) except Exception as e: