Skip to content

Commit d7cab21

Browse files
author
Mice Xia
committed
1) rename RevertToSnapshotCmd->RevertToVMSnapshotCmd 2) add marvin test for vm snapshot
1 parent 2510bf0 commit d7cab21

6 files changed

Lines changed: 353 additions & 8 deletions

File tree

api/src/org/apache/cloudstack/api/command/user/vmsnapshot/RevertToSnapshotCmd.java renamed to api/src/org/apache/cloudstack/api/command/user/vmsnapshot/RevertToVMSnapshotCmd.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@
3737
import com.cloud.uservm.UserVm;
3838
import com.cloud.vm.snapshot.VMSnapshot;
3939

40-
@APICommand(name = "revertToSnapshot",description = "Revert VM from a vmsnapshot.", responseObject = UserVmResponse.class, since="4.2.0")
41-
public class RevertToSnapshotCmd extends BaseAsyncCmd {
40+
@APICommand(name = "revertToVMSnapshot",description = "Revert VM from a vmsnapshot.", responseObject = UserVmResponse.class, since="4.2.0")
41+
public class RevertToVMSnapshotCmd extends BaseAsyncCmd {
4242
public static final Logger s_logger = Logger
43-
.getLogger(RevertToSnapshotCmd.class.getName());
44-
private static final String s_name = "reverttosnapshotresponse";
43+
.getLogger(RevertToVMSnapshotCmd.class.getName());
44+
private static final String s_name = "reverttovmsnapshotresponse";
4545

4646
@Parameter(name = ApiConstants.VM_SNAPSHOT_ID, type = CommandType.UUID, required = true,entityType=VMSnapshotResponse.class,description = "The ID of the vm snapshot")
4747
private Long vmSnapShotId;

client/tomcatconf/commands.properties.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ removeFromGlobalLoadBalancerRule=15
569569
listVMSnapshot=15
570570
createVMSnapshot=15
571571
deleteVMSnapshot=15
572-
revertToSnapshot=15
572+
revertToVMSnapshot=15
573573

574574
#### Baremetal commands
575575
addBaremetalHost=1

server/src/com/cloud/server/ManagementServerImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@
256256
import org.apache.cloudstack.api.command.user.vmsnapshot.CreateVMSnapshotCmd;
257257
import org.apache.cloudstack.api.command.user.vmsnapshot.DeleteVMSnapshotCmd;
258258
import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd;
259-
import org.apache.cloudstack.api.command.user.vmsnapshot.RevertToSnapshotCmd;
259+
import org.apache.cloudstack.api.command.user.vmsnapshot.RevertToVMSnapshotCmd;
260260
import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd;
261261
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
262262
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
@@ -2524,7 +2524,7 @@ public List<Class<?>> getCommands() {
25242524
cmdList.add(ListZonesByCmd.class);
25252525
cmdList.add(ListVMSnapshotCmd.class);
25262526
cmdList.add(CreateVMSnapshotCmd.class);
2527-
cmdList.add(RevertToSnapshotCmd.class);
2527+
cmdList.add(RevertToVMSnapshotCmd.class);
25282528
cmdList.add(DeleteVMSnapshotCmd.class);
25292529
cmdList.add(AddIpToVmNicCmd.class);
25302530
cmdList.add(RemoveIpFromVmNicCmd.class);
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
# Import Local Modules
19+
import marvin
20+
from nose.plugins.attrib import attr
21+
from marvin.cloudstackTestCase import *
22+
from marvin.cloudstackAPI import *
23+
from marvin.integration.lib.utils import *
24+
from marvin.integration.lib.base import *
25+
from marvin.integration.lib.common import *
26+
from marvin.remoteSSHClient import remoteSSHClient
27+
28+
class Services:
29+
"""Test Snapshots Services
30+
"""
31+
32+
def __init__(self):
33+
self.services = {
34+
"account": {
35+
"email": "test@test.com",
36+
"firstname": "Test",
37+
"lastname": "User",
38+
"username": "test",
39+
# Random characters are appended for unique
40+
# username
41+
"password": "password",
42+
},
43+
"service_offering": {
44+
"name": "Tiny Instance",
45+
"displaytext": "Tiny Instance",
46+
"cpunumber": 1,
47+
"cpuspeed": 200, # in MHz
48+
"memory": 256, # In MBs
49+
},
50+
"server": {
51+
"displayname": "TestVM",
52+
"username": "root",
53+
"password": "password",
54+
"ssh_port": 22,
55+
"hypervisor": 'XenServer',
56+
"privateport": 22,
57+
"publicport": 22,
58+
"protocol": 'TCP',
59+
},
60+
"mgmt_server": {
61+
"ipaddress": '1.2.2.152',
62+
"username": "root",
63+
"password": "password",
64+
"port": 22,
65+
},
66+
"templates": {
67+
"displaytext": 'Template',
68+
"name": 'Template',
69+
"ostype": "CentOS 5.3 (64-bit)",
70+
"templatefilter": 'self',
71+
},
72+
"test_dir": "/tmp",
73+
"random_data": "random.data",
74+
"snapshot_name":"TestSnapshot",
75+
"snapshot_displaytext":"Test",
76+
"ostype": "CentOS 5.3 (64-bit)",
77+
"sleep": 60,
78+
"timeout": 10,
79+
"mode": 'advanced', # Networking mode: Advanced, Basic
80+
}
81+
82+
class TestVmSnapshot(cloudstackTestCase):
83+
@classmethod
84+
def setUpClass(cls):
85+
cls.api_client = super(TestVmSnapshot, cls).getClsTestClient().getApiClient()
86+
cls.services = Services().services
87+
# Get Zone, Domain and templates
88+
cls.domain = get_domain(cls.api_client, cls.services)
89+
cls.zone = get_zone(cls.api_client, cls.services)
90+
91+
template = get_template(
92+
cls.api_client,
93+
cls.zone.id,
94+
cls.services["ostype"]
95+
)
96+
cls.services["domainid"] = cls.domain.id
97+
cls.services["server"]["zoneid"] = cls.zone.id
98+
cls.services["templates"]["ostypeid"] = template.ostypeid
99+
cls.services["zoneid"] = cls.zone.id
100+
101+
# Create VMs, NAT Rules etc
102+
cls.account = Account.create(
103+
cls.api_client,
104+
cls.services["account"],
105+
domainid=cls.domain.id
106+
)
107+
108+
cls.services["account"] = cls.account.name
109+
110+
cls.service_offering = ServiceOffering.create(
111+
cls.api_client,
112+
cls.services["service_offering"]
113+
)
114+
cls.virtual_machine = VirtualMachine.create(
115+
cls.api_client,
116+
cls.services["server"],
117+
templateid=template.id,
118+
accountid=cls.account.name,
119+
domainid=cls.account.domainid,
120+
serviceofferingid=cls.service_offering.id,
121+
mode=cls.services["mode"]
122+
)
123+
cls.random_data_0 = random_gen(100)
124+
cls._cleanup = [
125+
cls.service_offering,
126+
cls.account,
127+
]
128+
return
129+
130+
@classmethod
131+
def tearDownClass(cls):
132+
try:
133+
# Cleanup resources used
134+
cleanup_resources(cls.api_client, cls._cleanup)
135+
except Exception as e:
136+
raise Exception("Warning: Exception during cleanup : %s" % e)
137+
return
138+
139+
def setUp(self):
140+
self.apiclient = self.testClient.getApiClient()
141+
self.dbclient = self.testClient.getDbConnection()
142+
self.cleanup = []
143+
return
144+
145+
def tearDown(self):
146+
try:
147+
# Clean up, terminate the created instance, volumes and snapshots
148+
cleanup_resources(self.apiclient, self.cleanup)
149+
except Exception as e:
150+
raise Exception("Warning: Exception during cleanup : %s" % e)
151+
return
152+
153+
@attr(tags=["advanced", "advancedns", "smoke"])
154+
def test_01_create_vm_snapshots(self):
155+
156+
try:
157+
# Login to VM and write data to file system
158+
ssh_client = self.virtual_machine.get_ssh_client()
159+
160+
cmds = [
161+
"echo %s > %s/%s" % (self.random_data_0, self.services["test_dir"], self.services["random_data"]),
162+
"cat %s/%s" % (self.services["test_dir"], self.services["random_data"])
163+
]
164+
165+
for c in cmds:
166+
self.debug(c)
167+
result = ssh_client.execute(c)
168+
self.debug(result)
169+
170+
except Exception:
171+
self.fail("SSH failed for Virtual machine: %s" %
172+
self.virtual_machine.ipaddress)
173+
self.assertEqual(
174+
self.random_data_0,
175+
result[0],
176+
"Check the random data has be write into temp file!"
177+
)
178+
179+
time.sleep(self.services["sleep"])
180+
181+
vm_snapshot = VmSnapshot.create(
182+
self.apiclient,
183+
self.virtual_machine.id,
184+
"false",
185+
self.services["snapshot_name"],
186+
self.services["snapshot_displaytext"]
187+
)
188+
self.assertEqual(
189+
vm_snapshot.state,
190+
"Ready",
191+
"Check the snapshot of vm is ready!"
192+
)
193+
return
194+
195+
@attr(tags=["advanced", "advancedns", "smoke"])
196+
def test_02_revert_vm_snapshots(self):
197+
try:
198+
ssh_client = self.virtual_machine.get_ssh_client()
199+
200+
cmds = [
201+
"rm -rf %s/%s" % (self.services["test_dir"], self.services["random_data"]),
202+
"ls %s/%s" % (self.services["test_dir"], self.services["random_data"])
203+
]
204+
205+
for c in cmds:
206+
self.debug(c)
207+
result = ssh_client.execute(c)
208+
self.debug(result)
209+
210+
except Exception:
211+
self.fail("SSH failed for Virtual machine: %s" %
212+
self.virtual_machine.ipaddress)
213+
214+
if str(result[0]).index("No such file or directory") == -1:
215+
self.fail("Check the random data has be delete from temp file!")
216+
217+
time.sleep(self.services["sleep"])
218+
219+
list_snapshot_response = VmSnapshot.list(self.apiclient,vmid=self.virtual_machine.id,listall=True)
220+
221+
self.assertEqual(
222+
isinstance(list_snapshot_response, list),
223+
True,
224+
"Check list response returns a valid list"
225+
)
226+
self.assertNotEqual(
227+
list_snapshot_response,
228+
None,
229+
"Check if snapshot exists in ListSnapshot"
230+
)
231+
232+
self.assertEqual(
233+
list_snapshot_response[0].state,
234+
"Ready",
235+
"Check the snapshot of vm is ready!"
236+
)
237+
238+
VmSnapshot.revertToSnapshot(self.apiclient,list_snapshot_response[0].id)
239+
240+
list_vm_response = list_virtual_machines(
241+
self.apiclient,
242+
id=self.virtual_machine.id
243+
)
244+
245+
self.assertEqual(
246+
list_vm_response[0].state,
247+
"Stopped",
248+
"Check the state of vm is Stopped!"
249+
)
250+
251+
cmd = startVirtualMachine.startVirtualMachineCmd()
252+
cmd.id = list_vm_response[0].id
253+
self.apiclient.startVirtualMachine(cmd)
254+
255+
time.sleep(self.services["sleep"])
256+
257+
try:
258+
ssh_client = self.virtual_machine.get_ssh_client(reconnect=True)
259+
260+
cmds = [
261+
"cat %s/%s" % (self.services["test_dir"], self.services["random_data"])
262+
]
263+
264+
for c in cmds:
265+
self.debug(c)
266+
result = ssh_client.execute(c)
267+
self.debug(result)
268+
269+
except Exception:
270+
self.fail("SSH failed for Virtual machine: %s" %
271+
self.virtual_machine.ipaddress)
272+
273+
self.assertEqual(
274+
self.random_data_0,
275+
result[0],
276+
"Check the random data is equal with the ramdom file!"
277+
)
278+
@attr(tags=["advanced", "advancedns", "smoke"])
279+
def test_03_delete_vm_snapshots(self):
280+
281+
list_snapshot_response = VmSnapshot.list(self.apiclient,vmid=self.virtual_machine.id,listall=True)
282+
283+
self.assertEqual(
284+
isinstance(list_snapshot_response, list),
285+
True,
286+
"Check list response returns a valid list"
287+
)
288+
self.assertNotEqual(
289+
list_snapshot_response,
290+
None,
291+
"Check if snapshot exists in ListSnapshot"
292+
)
293+
"""
294+
cmd = deleteVMSnapshot.deleteVMSnapshotCmd()
295+
cmd.vmsnapshotid = list_snapshot_response[0].id
296+
self.apiclient.deleteVMSnapshot(cmd)
297+
"""
298+
VmSnapshot.deleteVMSnapshot(self.apiclient,list_snapshot_response[0].id)
299+
300+
time.sleep(self.services["sleep"]*3)
301+
302+
list_snapshot_response = VmSnapshot.list(self.apiclient,vmid=self.virtual_machine.id,listall=True)
303+
304+
self.assertEqual(
305+
list_snapshot_response,
306+
None,
307+
"Check list vm snapshot has be deleted"
308+
)

tools/marvin/marvin/integration/lib/base.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3045,3 +3045,40 @@ def list(cls, apiclient, **kwargs):
30453045
cmd = listCiscoAsa1000vResources.listCiscoAsa1000vResourcesCmd()
30463046
[setattr(cmd, k, v) for k, v in kwargs.items()]
30473047
return(apiclient.listCiscoAsa1000vResources(cmd))
3048+
3049+
class VmSnapshot:
3050+
"""Manage VM Snapshot life cycle"""
3051+
def __init__(self, items):
3052+
self.__dict__.update(items)
3053+
@classmethod
3054+
def create(cls,apiclient,vmid,snapshotmemory="false",name=None,description=None):
3055+
cmd = createVMSnapshot.createVMSnapshotCmd()
3056+
cmd.virtualmachineid = vmid
3057+
3058+
if snapshotmemory:
3059+
cmd.snapshotmemory = snapshotmemory
3060+
if name:
3061+
cmd.name = name
3062+
if description:
3063+
cmd.description = description
3064+
return VmSnapshot(apiclient.createVMSnapshot(cmd).__dict__)
3065+
3066+
@classmethod
3067+
def list(cls, apiclient, **kwargs):
3068+
cmd = listVMSnapshot.listVMSnapshotCmd()
3069+
[setattr(cmd, k, v) for k, v in kwargs.items()]
3070+
return(apiclient.listVMSnapshot(cmd))
3071+
3072+
@classmethod
3073+
def revertToSnapshot(cls, apiclient,vmsnapshotid):
3074+
cmd = revertToVMSnapshot.revertToVMSnapshotCmd()
3075+
cmd.vmsnapshotid = vmsnapshotid
3076+
3077+
return apiclient.revertToVMSnapshot(cmd)
3078+
3079+
@classmethod
3080+
def deleteVMSnapshot(cls,apiclient,vmsnapshotid):
3081+
cmd = deleteVMSnapshot.deleteVMSnapshotCmd()
3082+
cmd.vmsnapshotid = vmsnapshotid
3083+
3084+
return apiclient.deleteVMSnapshot(cmd)

0 commit comments

Comments
 (0)