You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ko...@apache.org on 2014/07/07 10:01:44 UTC

git commit: updated refs/heads/master to a413536

Repository: cloudstack
Updated Branches:
  refs/heads/master fc23c70a1 -> a413536f9


Added a simulator based test for VM sync


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

Branch: refs/heads/master
Commit: a413536f90c0e3b1d43862c0d2b9c1bf292cfc8a
Parents: fc23c70
Author: Koushik Das <ko...@apache.org>
Authored: Mon Jul 7 12:53:05 2014 +0530
Committer: Koushik Das <ko...@apache.org>
Committed: Mon Jul 7 12:57:55 2014 +0530

----------------------------------------------------------------------
 .../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         |  10 +-
 tools/marvin/marvin/lib/base.py                 |   4 +-
 5 files changed, 167 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a413536f/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/a413536f/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/a413536f/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/a413536f/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 5607217..19b9aa4 100644
--- a/tools/marvin/marvin/config/test_data.py
+++ b/tools/marvin/marvin/config/test_data.py
@@ -90,7 +90,7 @@ test_data = {
         "memory": 128,
 
         "tiny": {
-                "name": "Tiny Instance",
+            "name": "Tiny Instance",
             "displaytext": "Tiny Instance",
             "cpunumber": 1,
             "cpuspeed": 100,
@@ -126,6 +126,14 @@ test_data = {
             "hosttags": "ha",
             "offerha": True,
         },
+        "taggedsmall": {
+            "name": "Tagged Small Instance",
+            "displaytext": "Tagged Small Instance",
+            "cpunumber": 1,
+            "cpuspeed": 100,
+            "memory": 256,
+            "hosttags": "vmsync",
+        },
     },
     "disk_offering": {
         "name": "Disk offering",

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a413536f/tools/marvin/marvin/lib/base.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py
index 2ef6f82..445faba 100755
--- a/tools/marvin/marvin/lib/base.py
+++ b/tools/marvin/marvin/lib/base.py
@@ -4564,7 +4564,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()
         cmd.zoneid = zoneid
@@ -4576,7 +4576,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: