mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Detail: Integration tests use these libraries (base,utils,common) for simplifying the usage of the API. These define the verbs of each entity's usage (create, delete, add etc). For the CLI to present the simplified API we'll leverage the integration libraries. + Fixes to setup-test-data.sh - kvm and xen each use a different version of the built-in Cent OS template, 5.5 and 5.3 namely. At a later point the setup-test-data script needs to be obsoleted. ostypeids in tests should directly be determined from listOsTypes API calls Signed-off-by: Prasanna Santhanam <tsp@apache.org> 1351520707 +0530
2517 lines
102 KiB
Python
2517 lines
102 KiB
Python
# 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.
|
|
""" P1 tests for Snapshots
|
|
"""
|
|
#Import Local Modules
|
|
import marvin
|
|
from nose.plugins.attrib import attr
|
|
from marvin.cloudstackTestCase import *
|
|
from marvin.cloudstackAPI import *
|
|
from marvin.integration.lib.utils import *
|
|
from marvin.integration.lib.base import *
|
|
from marvin.integration.lib.common import *
|
|
from marvin.remoteSSHClient import remoteSSHClient
|
|
|
|
|
|
class Services:
|
|
"""Test Snapshots Services
|
|
"""
|
|
|
|
def __init__(self):
|
|
self.services = {
|
|
"account": {
|
|
"email": "test@test.com",
|
|
"firstname": "Test",
|
|
"lastname": "User",
|
|
"username": "test",
|
|
# Random characters are appended for unique
|
|
# username
|
|
"password": "password",
|
|
},
|
|
"service_offering": {
|
|
"name": "Tiny Instance",
|
|
"displaytext": "Tiny Instance",
|
|
"cpunumber": 1,
|
|
"cpuspeed": 200, # in MHz
|
|
"memory": 256, # In MBs
|
|
},
|
|
"disk_offering": {
|
|
"displaytext": "Small Disk",
|
|
"name": "Small Disk",
|
|
"disksize": 1
|
|
},
|
|
"server_with_disk":
|
|
{
|
|
"displayname": "Test VM -With Disk",
|
|
"username": "root",
|
|
"password": "password",
|
|
"ssh_port": 22,
|
|
"hypervisor": 'XenServer',
|
|
"privateport": 22,
|
|
"publicport": 22,
|
|
"protocol": 'TCP',
|
|
},
|
|
|
|
"server_without_disk":
|
|
{
|
|
"displayname": "Test VM-No Disk",
|
|
"username": "root",
|
|
"password": "password",
|
|
"ssh_port": 22,
|
|
"hypervisor": 'XenServer',
|
|
"privateport": 22,
|
|
# For NAT rule creation
|
|
"publicport": 22,
|
|
"protocol": 'TCP',
|
|
},
|
|
"server": {
|
|
"displayname": "TestVM",
|
|
"username": "root",
|
|
"password": "password",
|
|
"ssh_port": 22,
|
|
"hypervisor": 'XenServer',
|
|
"privateport": 22,
|
|
"publicport": 22,
|
|
"protocol": 'TCP',
|
|
},
|
|
"mgmt_server": {
|
|
"ipaddress": '192.168.100.21',
|
|
"username": "root",
|
|
"password": "password",
|
|
"port": 22,
|
|
},
|
|
"recurring_snapshot": {
|
|
"intervaltype": 'HOURLY',
|
|
# Frequency of snapshots
|
|
"maxsnaps": 1, # Should be min 2
|
|
"schedule": 1,
|
|
"timezone": 'US/Arizona',
|
|
# Timezone Formats - http://cloud.mindtouch.us/CloudStack_Documentation/Developer's_Guide%3A_CloudStack
|
|
},
|
|
"templates": {
|
|
"displaytext": 'Template',
|
|
"name": 'Template',
|
|
"ostypeid": '01853327-513e-4508-9628-f1f55db1946f',
|
|
"templatefilter": 'self',
|
|
},
|
|
"diskdevice": "/dev/xvda",
|
|
"diskname": "TestDiskServ",
|
|
"size": 1, # GBs
|
|
|
|
"mount_dir": "/mnt/tmp",
|
|
"sub_dir": "test",
|
|
"sub_lvl_dir1": "test1",
|
|
"sub_lvl_dir2": "test2",
|
|
"random_data": "random.data",
|
|
|
|
"ostypeid": '01853327-513e-4508-9628-f1f55db1946f',
|
|
# Cent OS 5.3 (64 bit)
|
|
"sleep": 60,
|
|
"timeout": 10,
|
|
"mode": 'advanced', # Networking mode: Advanced, Basic
|
|
}
|
|
|
|
|
|
class TestSnapshotRootDisk(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.api_client = super(TestSnapshotRootDisk, 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["ostypeid"]
|
|
)
|
|
cls.services["domainid"] = cls.domain.id
|
|
cls.services["server_without_disk"]["zoneid"] = cls.zone.id
|
|
cls.services["template"] = template.id
|
|
cls.services["zoneid"] = cls.zone.id
|
|
|
|
# Create VMs, NAT Rules etc
|
|
cls.account = Account.create(
|
|
cls.api_client,
|
|
cls.services["account"],
|
|
domainid=cls.domain.id
|
|
)
|
|
|
|
cls.services["account"] = cls.account.account.name
|
|
|
|
cls.service_offering = ServiceOffering.create(
|
|
cls.api_client,
|
|
cls.services["service_offering"]
|
|
)
|
|
cls.virtual_machine = cls.virtual_machine_with_disk = \
|
|
VirtualMachine.create(
|
|
cls.api_client,
|
|
cls.services["server_without_disk"],
|
|
templateid=template.id,
|
|
accountid=cls.account.account.name,
|
|
domainid=cls.account.account.domainid,
|
|
serviceofferingid=cls.service_offering.id,
|
|
mode=cls.services["mode"]
|
|
)
|
|
cls._cleanup = [
|
|
cls.service_offering,
|
|
cls.account,
|
|
]
|
|
return
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
try:
|
|
#Cleanup resources used
|
|
cleanup_resources(cls.api_client, cls._cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
def setUp(self):
|
|
self.apiclient = self.testClient.getApiClient()
|
|
self.dbclient = self.testClient.getDbConnection()
|
|
self.cleanup = []
|
|
return
|
|
|
|
def tearDown(self):
|
|
try:
|
|
#Clean up, terminate the created instance, volumes and snapshots
|
|
cleanup_resources(self.apiclient, self.cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
@attr(speed = "slow")
|
|
@attr(tags = ["advanced", "advancedns", "smoke"])
|
|
def test_01_snapshot_root_disk(self):
|
|
"""Test Snapshot Root Disk
|
|
"""
|
|
|
|
# Validate the following
|
|
# 1. listSnapshots should list the snapshot that was created.
|
|
# 2. verify that secondary storage NFS share contains
|
|
# the reqd volume under
|
|
# /secondary/snapshots//$account_id/$volumeid/$snapshot_uuid
|
|
# 3. verify backup_snap_id was non null in the `snapshots` table
|
|
|
|
volumes = list_volumes(
|
|
self.apiclient,
|
|
virtualmachineid=self.virtual_machine_with_disk.id,
|
|
type='ROOT',
|
|
listall=True
|
|
)
|
|
|
|
snapshot = Snapshot.create(
|
|
self.apiclient,
|
|
volumes[0].id,
|
|
account=self.account.account.name,
|
|
domainid=self.account.account.domainid
|
|
)
|
|
self.debug("Snapshot created: ID - %s" % snapshot.id)
|
|
|
|
snapshots = list_snapshots(
|
|
self.apiclient,
|
|
id=snapshot.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(snapshots, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
|
|
self.assertNotEqual(
|
|
snapshots,
|
|
None,
|
|
"Check if result exists in list item call"
|
|
)
|
|
self.assertEqual(
|
|
snapshots[0].id,
|
|
snapshot.id,
|
|
"Check resource id in list resources call"
|
|
)
|
|
self.debug(
|
|
"select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \
|
|
% str(snapshot.id)
|
|
)
|
|
qresultset = self.dbclient.execute(
|
|
"select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \
|
|
% str(snapshot.id)
|
|
)
|
|
self.assertNotEqual(
|
|
len(qresultset),
|
|
0,
|
|
"Check DB Query result set"
|
|
)
|
|
|
|
qresult = qresultset[0]
|
|
|
|
snapshot_uuid = qresult[0] # backup_snap_id = snapshot UUID
|
|
account_id = qresult[1]
|
|
volume_id = qresult[2]
|
|
|
|
self.assertNotEqual(
|
|
str(snapshot_uuid),
|
|
'NULL',
|
|
"Check if backup_snap_id is not null"
|
|
)
|
|
|
|
# Get the Secondary Storage details from list Hosts
|
|
hosts = list_hosts(
|
|
self.apiclient,
|
|
type='SecondaryStorage',
|
|
zoneid=self.zone.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(hosts, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
uuids = []
|
|
for host in hosts:
|
|
# hosts[0].name = "nfs://192.168.100.21/export/test"
|
|
parse_url = (host.name).split('/')
|
|
# parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test']
|
|
|
|
# Split IP address and export path from name
|
|
sec_storage_ip = parse_url[2]
|
|
# Sec Storage IP: 192.168.100.21
|
|
|
|
export_path = '/'.join(parse_url[3:])
|
|
# Export path: export/test
|
|
|
|
try:
|
|
# Login to VM to check snapshot present on sec disk
|
|
ssh_client = self.virtual_machine_with_disk.get_ssh_client()
|
|
|
|
cmds = [
|
|
"mkdir -p %s" % self.services["mount_dir"],
|
|
"mount %s/%s %s" % (
|
|
sec_storage_ip,
|
|
export_path,
|
|
self.services["mount_dir"]
|
|
),
|
|
"ls %s/snapshots/%s/%s" % (
|
|
self.services["mount_dir"],
|
|
account_id,
|
|
volume_id
|
|
),
|
|
]
|
|
|
|
for c in cmds:
|
|
self.debug(c)
|
|
result = ssh_client.execute(c)
|
|
self.debug(result)
|
|
|
|
except Exception:
|
|
self.fail("SSH failed for Virtual machine: %s" %
|
|
self.virtual_machine_with_disk.ipaddress)
|
|
|
|
uuids.append(result)
|
|
# Unmount the Sec Storage
|
|
cmds = [
|
|
"umount %s" % (self.services["mount_dir"]),
|
|
]
|
|
try:
|
|
for c in cmds:
|
|
self.debug(c)
|
|
result = ssh_client.execute(c)
|
|
self.debug(result)
|
|
|
|
except Exception as e:
|
|
self.fail("SSH failed for Virtual machine: %s" %
|
|
self.virtual_machine_with_disk.ipaddress)
|
|
|
|
res = str(uuids)
|
|
# Check snapshot UUID in secondary storage and database
|
|
self.assertEqual(
|
|
res.count(snapshot_uuid),
|
|
1,
|
|
"Check snapshot UUID in secondary storage and database"
|
|
)
|
|
return
|
|
|
|
|
|
class TestSnapshots(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.api_client = super(TestSnapshots, 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)
|
|
cls.disk_offering = DiskOffering.create(
|
|
cls.api_client,
|
|
cls.services["disk_offering"]
|
|
)
|
|
template = get_template(
|
|
cls.api_client,
|
|
cls.zone.id,
|
|
cls.services["ostypeid"]
|
|
)
|
|
|
|
cls.services["domainid"] = cls.domain.id
|
|
cls.services["server_with_disk"]["zoneid"] = cls.zone.id
|
|
cls.services["server_with_disk"]["diskoffering"] = cls.disk_offering.id
|
|
|
|
cls.services["server_without_disk"]["zoneid"] = cls.zone.id
|
|
|
|
cls.services["template"] = template.id
|
|
cls.services["zoneid"] = cls.zone.id
|
|
cls.services["diskoffering"] = cls.disk_offering.id
|
|
|
|
# Create VMs, NAT Rules etc
|
|
cls.account = Account.create(
|
|
cls.api_client,
|
|
cls.services["account"],
|
|
domainid=cls.domain.id
|
|
)
|
|
|
|
cls.services["account"] = cls.account.account.name
|
|
|
|
cls.service_offering = ServiceOffering.create(
|
|
cls.api_client,
|
|
cls.services["service_offering"]
|
|
)
|
|
cls.virtual_machine = cls.virtual_machine_with_disk = \
|
|
VirtualMachine.create(
|
|
cls.api_client,
|
|
cls.services["server_with_disk"],
|
|
templateid=template.id,
|
|
accountid=cls.account.account.name,
|
|
domainid=cls.account.account.domainid,
|
|
serviceofferingid=cls.service_offering.id,
|
|
mode=cls.services["mode"]
|
|
)
|
|
cls.virtual_machine_without_disk = \
|
|
VirtualMachine.create(
|
|
cls.api_client,
|
|
cls.services["server_without_disk"],
|
|
templateid=template.id,
|
|
accountid=cls.account.account.name,
|
|
domainid=cls.account.account.domainid,
|
|
serviceofferingid=cls.service_offering.id,
|
|
mode=cls.services["mode"]
|
|
)
|
|
cls._cleanup = [
|
|
cls.service_offering,
|
|
cls.disk_offering,
|
|
cls.account,
|
|
]
|
|
return
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
try:
|
|
#Cleanup resources used
|
|
cleanup_resources(cls.api_client, cls._cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
def setUp(self):
|
|
self.apiclient = self.testClient.getApiClient()
|
|
self.dbclient = self.testClient.getDbConnection()
|
|
self.cleanup = []
|
|
return
|
|
|
|
def tearDown(self):
|
|
try:
|
|
#Clean up, terminate the created instance, volumes and snapshots
|
|
cleanup_resources(self.apiclient, self.cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
@attr(speed = "slow")
|
|
@attr(tags = ["advanced", "advancedns", "smoke"])
|
|
def test_02_snapshot_data_disk(self):
|
|
"""Test Snapshot Data Disk
|
|
"""
|
|
|
|
volume = list_volumes(
|
|
self.apiclient,
|
|
virtualmachineid=self.virtual_machine_with_disk.id,
|
|
type='DATADISK',
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(volume, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
|
|
self.debug("Creating a Snapshot from data volume: %s" % volume[0].id)
|
|
snapshot = Snapshot.create(
|
|
self.apiclient,
|
|
volume[0].id,
|
|
account=self.account.account.name,
|
|
domainid=self.account.account.domainid
|
|
)
|
|
snapshots = list_snapshots(
|
|
self.apiclient,
|
|
id=snapshot.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(snapshots, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertNotEqual(
|
|
snapshots,
|
|
None,
|
|
"Check if result exists in list item call"
|
|
)
|
|
self.assertEqual(
|
|
snapshots[0].id,
|
|
snapshot.id,
|
|
"Check resource id in list resources call"
|
|
)
|
|
self.debug(
|
|
"select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \
|
|
% str(snapshot.id)
|
|
)
|
|
qresultset = self.dbclient.execute(
|
|
"select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \
|
|
% str(snapshot.id)
|
|
)
|
|
self.assertNotEqual(
|
|
len(qresultset),
|
|
0,
|
|
"Check DB Query result set"
|
|
)
|
|
|
|
qresult = qresultset[0]
|
|
snapshot_uuid = qresult[0] # backup_snap_id = snapshot UUID
|
|
account_id = qresult[1]
|
|
volume_id = qresult[2]
|
|
|
|
self.assertNotEqual(
|
|
str(snapshot_uuid),
|
|
'NULL',
|
|
"Check if backup_snap_id is not null"
|
|
)
|
|
|
|
# Get the Secondary Storage details from list Hosts
|
|
hosts = list_hosts(
|
|
self.apiclient,
|
|
type='SecondaryStorage',
|
|
zoneid=self.zone.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(hosts, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
uuids = []
|
|
for host in hosts:
|
|
# hosts[0].name = "nfs://192.168.100.21/export"
|
|
parse_url = (host.name).split('/')
|
|
# parse_url = ['nfs:', '', '192.168.100.21', 'export']
|
|
|
|
# Split IP address and export path from name
|
|
sec_storage_ip = parse_url[2]
|
|
# Sec Storage IP: 192.168.100.21
|
|
|
|
export_path = '/'.join(parse_url[3:])
|
|
# Export path: export
|
|
|
|
try:
|
|
# Login to VM to check snapshot present on sec disk
|
|
ssh_client = self.virtual_machine_with_disk.get_ssh_client()
|
|
|
|
cmds = [
|
|
"mkdir -p %s" % self.services["mount_dir"],
|
|
"mount %s/%s %s" % (
|
|
sec_storage_ip,
|
|
export_path,
|
|
self.services["mount_dir"]
|
|
),
|
|
"ls %s/snapshots/%s/%s" % (
|
|
self.services["mount_dir"],
|
|
account_id,
|
|
volume_id
|
|
),
|
|
]
|
|
for c in cmds:
|
|
self.debug(c)
|
|
result = ssh_client.execute(c)
|
|
self.debug(result)
|
|
|
|
except Exception as e:
|
|
self.fail("SSH failed for VM with IP: %s" %
|
|
self.virtual_machine_with_disk.ipaddress)
|
|
|
|
uuids.append(result)
|
|
# Unmount the Sec Storage
|
|
cmds = [
|
|
"umount %s" % (self.services["mount_dir"]),
|
|
]
|
|
try:
|
|
for c in cmds:
|
|
self.debug(c)
|
|
ssh_client.execute(c)
|
|
|
|
except Exception as e:
|
|
self.fail("SSH failed for VM with IP: %s" %
|
|
self.virtual_machine_with_disk.ipaddress)
|
|
|
|
res = str(uuids)
|
|
# Check snapshot UUID in secondary storage and database
|
|
self.assertEqual(
|
|
res.count(snapshot_uuid),
|
|
1,
|
|
"Check snapshot UUID in secondary storage and database"
|
|
)
|
|
return
|
|
|
|
@attr(speed = "slow")
|
|
@attr(tags = ["advanced", "advancedns", "smoke"])
|
|
def test_03_volume_from_snapshot(self):
|
|
"""Create volumes from snapshots
|
|
"""
|
|
#1. Login to machine; create temp/test directories on data volume
|
|
#2. Snapshot the Volume
|
|
#3. Create another Volume from snapshot
|
|
#4. Mount/Attach volume to another server
|
|
#5. Compare data
|
|
random_data_0 = random_gen(100)
|
|
random_data_1 = random_gen(100)
|
|
|
|
try:
|
|
ssh_client = self.virtual_machine.get_ssh_client()
|
|
|
|
#Format partition using ext3
|
|
format_volume_to_ext3(
|
|
ssh_client,
|
|
self.services["diskdevice"]
|
|
)
|
|
cmds = [
|
|
"mkdir -p %s" % self.services["mount_dir"],
|
|
"mount %s1 %s" % (
|
|
self.services["diskdevice"],
|
|
self.services["mount_dir"]
|
|
),
|
|
"mkdir -p %s/%s/{%s,%s} " % (
|
|
self.services["mount_dir"],
|
|
self.services["sub_dir"],
|
|
self.services["sub_lvl_dir1"],
|
|
self.services["sub_lvl_dir2"]
|
|
),
|
|
"echo %s > %s/%s/%s/%s" % (
|
|
random_data_0,
|
|
self.services["mount_dir"],
|
|
self.services["sub_dir"],
|
|
self.services["sub_lvl_dir1"],
|
|
self.services["random_data"]
|
|
),
|
|
"echo %s > %s/%s/%s/%s" % (
|
|
random_data_1,
|
|
self.services["mount_dir"],
|
|
self.services["sub_dir"],
|
|
self.services["sub_lvl_dir2"],
|
|
self.services["random_data"]
|
|
),
|
|
]
|
|
for c in cmds:
|
|
self.debug(c)
|
|
ssh_client.execute(c)
|
|
|
|
except Exception as e:
|
|
self.fail("SSH failed for VM with IP: %s" %
|
|
self.virtual_machine.ipaddress)
|
|
# Unmount the Sec Storage
|
|
cmds = [
|
|
"umount %s" % (self.services["mount_dir"]),
|
|
]
|
|
|
|
try:
|
|
for c in cmds:
|
|
self.debug(c)
|
|
ssh_client.execute(c)
|
|
|
|
except Exception as e:
|
|
self.fail("SSH failed for VM with IP: %s" %
|
|
self.virtual_machine.ipaddress)
|
|
|
|
list_volume_response = list_volumes(
|
|
self.apiclient,
|
|
virtualmachineid=self.virtual_machine.id,
|
|
type='DATADISK',
|
|
listall=True
|
|
)
|
|
|
|
volume_response = list_volume_response[0]
|
|
#Create snapshot from attached volume
|
|
snapshot = Snapshot.create(
|
|
self.apiclient,
|
|
volume_response.id,
|
|
account=self.account.account.name,
|
|
domainid=self.account.account.domainid
|
|
)
|
|
self.debug("Created Snapshot from volume: %s" % volume_response.id)
|
|
|
|
#Create volume from snapshot
|
|
self.debug("Creating volume from snapshot: %s" % snapshot.id)
|
|
volume = Volume.create_from_snapshot(
|
|
self.apiclient,
|
|
snapshot.id,
|
|
self.services,
|
|
account=self.account.account.name,
|
|
domainid=self.account.account.domainid
|
|
)
|
|
|
|
volumes = list_volumes(
|
|
self.apiclient,
|
|
id=volume.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(volumes, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertNotEqual(
|
|
len(volumes),
|
|
None,
|
|
"Check Volume list Length"
|
|
)
|
|
|
|
self.assertEqual(
|
|
volumes[0].id,
|
|
volume.id,
|
|
"Check Volume in the List Volumes"
|
|
)
|
|
#Attaching volume to new VM
|
|
new_virtual_machine = self.virtual_machine_without_disk
|
|
self.cleanup.append(new_virtual_machine)
|
|
|
|
cmd = attachVolume.attachVolumeCmd()
|
|
cmd.id = volume.id
|
|
cmd.virtualmachineid = new_virtual_machine.id
|
|
self.apiclient.attachVolume(cmd)
|
|
|
|
try:
|
|
#Login to VM to verify test directories and files
|
|
ssh = new_virtual_machine.get_ssh_client()
|
|
|
|
cmds = [
|
|
"mkdir -p %s" % self.services["mount_dir"],
|
|
"mount %s1 %s" % (
|
|
self.services["diskdevice"],
|
|
self.services["mount_dir"]
|
|
),
|
|
]
|
|
|
|
for c in cmds:
|
|
self.debug(c)
|
|
result = ssh.execute(c)
|
|
self.debug(result)
|
|
|
|
returned_data_0 = ssh.execute("cat %s/%s/%s/%s" % (
|
|
self.services["mount_dir"],
|
|
self.services["sub_dir"],
|
|
self.services["sub_lvl_dir1"],
|
|
self.services["random_data"]
|
|
))
|
|
returned_data_1 = ssh.execute("cat %s/%s/%s/%s" % (
|
|
self.services["mount_dir"],
|
|
self.services["sub_dir"],
|
|
self.services["sub_lvl_dir2"],
|
|
self.services["random_data"]
|
|
))
|
|
|
|
except Exception as e:
|
|
self.fail("SSH failed for VM with IP: %s" %
|
|
self.new_virtual_machine.ipaddress)
|
|
|
|
#Verify returned data
|
|
self.assertEqual(
|
|
random_data_0,
|
|
returned_data_0[0],
|
|
"Verify newly attached volume contents with existing one"
|
|
)
|
|
self.assertEqual(
|
|
random_data_1,
|
|
returned_data_1[0],
|
|
"Verify newly attached volume contents with existing one"
|
|
)
|
|
# Unmount the Sec Storage
|
|
cmds = [
|
|
"umount %s" % (self.services["mount_dir"]),
|
|
]
|
|
try:
|
|
for c in cmds:
|
|
ssh_client.execute(c)
|
|
|
|
except Exception as e:
|
|
self.fail("SSH failed for VM with IP: %s" %
|
|
self.new_virtual_machine.ipaddress)
|
|
return
|
|
|
|
@attr(speed = "slow")
|
|
@attr(tags = ["advanced", "advancedns", "smoke"])
|
|
def test_04_delete_snapshot(self):
|
|
"""Test Delete Snapshot
|
|
"""
|
|
|
|
#1. Snapshot the Volume
|
|
#2. Delete the snapshot
|
|
#3. Verify snapshot is removed by calling List Snapshots API
|
|
|
|
volumes = list_volumes(
|
|
self.apiclient,
|
|
virtualmachineid=self.virtual_machine.id,
|
|
type='DATADISK',
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(volumes, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
snapshot = Snapshot.create(
|
|
self.apiclient,
|
|
volumes[0].id,
|
|
account=self.account.account.name,
|
|
domainid=self.account.account.domainid
|
|
)
|
|
snapshot.delete(self.apiclient)
|
|
|
|
snapshots = list_snapshots(
|
|
self.apiclient,
|
|
id=snapshot.id
|
|
)
|
|
|
|
self.assertEqual(
|
|
snapshots,
|
|
None,
|
|
"Check if result exists in list item call"
|
|
)
|
|
return
|
|
|
|
@attr(speed = "slow")
|
|
@attr(tags = ["advanced", "advancedns", "smoke"])
|
|
def test_05_recurring_snapshot_root_disk(self):
|
|
"""Test Recurring Snapshot Root Disk
|
|
"""
|
|
#1. Create snapshot policy for root disk
|
|
#2. ListSnapshot policy should return newly created policy
|
|
#3. Verify only most recent number (maxsnaps) snapshots retailed
|
|
|
|
volume = list_volumes(
|
|
self.apiclient,
|
|
virtualmachineid=self.virtual_machine_with_disk.id,
|
|
type='ROOT',
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(volume, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
recurring_snapshot = SnapshotPolicy.create(
|
|
self.apiclient,
|
|
volume[0].id,
|
|
self.services["recurring_snapshot"]
|
|
)
|
|
self.cleanup.append(recurring_snapshot)
|
|
|
|
#ListSnapshotPolicy should return newly created policy
|
|
list_snapshots_policy = list_snapshot_policy(
|
|
self.apiclient,
|
|
id=recurring_snapshot.id,
|
|
volumeid=volume[0].id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_snapshots_policy, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertNotEqual(
|
|
list_snapshots_policy,
|
|
None,
|
|
"Check if result exists in list item call"
|
|
)
|
|
snapshots_policy = list_snapshots_policy[0]
|
|
self.assertEqual(
|
|
snapshots_policy.id,
|
|
recurring_snapshot.id,
|
|
"Check recurring snapshot id in list resources call"
|
|
)
|
|
self.assertEqual(
|
|
snapshots_policy.maxsnaps,
|
|
self.services["recurring_snapshot"]["maxsnaps"],
|
|
"Check interval type in list resources call"
|
|
)
|
|
# Sleep for (maxsnaps+1) hours to verify
|
|
# only maxsnaps snapshots are retained
|
|
time.sleep(
|
|
(self.services["recurring_snapshot"]["maxsnaps"]) * 3600
|
|
)
|
|
|
|
timeout = self.services["timeout"]
|
|
while True:
|
|
snapshots = list_snapshots(
|
|
self.apiclient,
|
|
volumeid=volume[0].id,
|
|
intervaltype=\
|
|
self.services["recurring_snapshot"]["intervaltype"],
|
|
snapshottype='RECURRING',
|
|
listall=True
|
|
)
|
|
|
|
if isinstance(snapshots, list):
|
|
break
|
|
|
|
elif timeout == 0:
|
|
raise Exception("List snapshots API call failed.")
|
|
|
|
time.sleep(1)
|
|
timeout = timeout - 1
|
|
|
|
self.assertEqual(
|
|
isinstance(snapshots, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
|
|
self.assertEqual(
|
|
len(snapshots),
|
|
self.services["recurring_snapshot"]["maxsnaps"],
|
|
"Check maximum number of recurring snapshots retained"
|
|
)
|
|
return
|
|
|
|
@attr(speed = "slow")
|
|
@attr(tags = ["advanced", "advancedns", "smoke"])
|
|
def test_06_recurring_snapshot_data_disk(self):
|
|
"""Test Recurring Snapshot data Disk
|
|
"""
|
|
#1. Create snapshot policy for data disk
|
|
#2. ListSnapshot policy should return newly created policy
|
|
#3. Verify only most recent number (maxsnaps) snapshots retailed
|
|
|
|
volume = list_volumes(
|
|
self.apiclient,
|
|
virtualmachineid=self.virtual_machine_with_disk.id,
|
|
type='DATADISK',
|
|
listall=True
|
|
)
|
|
|
|
self.assertEqual(
|
|
isinstance(volume, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
|
|
recurring_snapshot = SnapshotPolicy.create(
|
|
self.apiclient,
|
|
volume[0].id,
|
|
self.services["recurring_snapshot"]
|
|
)
|
|
self.cleanup.append(recurring_snapshot)
|
|
#ListSnapshotPolicy should return newly created policy
|
|
list_snapshots_policy = list_snapshot_policy(
|
|
self.apiclient,
|
|
id=recurring_snapshot.id,
|
|
volumeid=volume[0].id
|
|
)
|
|
|
|
self.assertEqual(
|
|
isinstance(list_snapshots_policy, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
|
|
self.assertNotEqual(
|
|
list_snapshots_policy,
|
|
None,
|
|
"Check if result exists in list item call"
|
|
)
|
|
snapshots_policy = list_snapshots_policy[0]
|
|
self.assertEqual(
|
|
snapshots_policy.id,
|
|
recurring_snapshot.id,
|
|
"Check recurring snapshot id in list resources call"
|
|
)
|
|
self.assertEqual(
|
|
snapshots_policy.maxsnaps,
|
|
self.services["recurring_snapshot"]["maxsnaps"],
|
|
"Check interval type in list resources call"
|
|
)
|
|
|
|
# Sleep for (maxsnaps) hours to verify only maxsnaps snapshots are
|
|
# retained
|
|
time.sleep(
|
|
(self.services["recurring_snapshot"]["maxsnaps"]) * 3600
|
|
)
|
|
|
|
timeout = self.services["timeout"]
|
|
while True:
|
|
snapshots = list_snapshots(
|
|
self.apiclient,
|
|
volumeid=volume[0].id,
|
|
intervaltype=\
|
|
self.services["recurring_snapshot"]["intervaltype"],
|
|
snapshottype='RECURRING',
|
|
listall=True
|
|
)
|
|
|
|
if isinstance(snapshots, list):
|
|
break
|
|
|
|
elif timeout == 0:
|
|
raise Exception("List snapshots API call failed.")
|
|
|
|
time.sleep(1)
|
|
timeout = timeout - 1
|
|
|
|
self.assertEqual(
|
|
isinstance(snapshots, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertEqual(
|
|
len(snapshots),
|
|
self.services["recurring_snapshot"]["maxsnaps"],
|
|
"Check maximum number of recurring snapshots retained"
|
|
)
|
|
return
|
|
|
|
@attr(speed = "slow")
|
|
@attr(tags = ["advanced", "advancedns", "smoke"])
|
|
def test_07_template_from_snapshot(self):
|
|
"""Create Template from snapshot
|
|
"""
|
|
|
|
#1. Login to machine; create temp/test directories on data volume
|
|
#2. Snapshot the Volume
|
|
#3. Create Template from snapshot
|
|
#4. Deploy Virtual machine using this template
|
|
#5. Login to newly created virtual machine
|
|
#6. Compare data
|
|
|
|
random_data_0 = random_gen(100)
|
|
random_data_1 = random_gen(100)
|
|
|
|
try:
|
|
#Login to virtual machine
|
|
ssh_client = self.virtual_machine.get_ssh_client()
|
|
|
|
cmds = [
|
|
"mkdir -p %s" % self.services["mount_dir"],
|
|
"mount %s1 %s" % (
|
|
self.services["rootdisk"],
|
|
self.services["mount_dir"]
|
|
),
|
|
"mkdir -p %s/%s/{%s,%s} " % (
|
|
self.services["mount_dir"],
|
|
self.services["sub_dir"],
|
|
self.services["sub_lvl_dir1"],
|
|
self.services["sub_lvl_dir2"]
|
|
),
|
|
"echo %s > %s/%s/%s/%s" % (
|
|
random_data_0,
|
|
self.services["mount_dir"],
|
|
self.services["sub_dir"],
|
|
self.services["sub_lvl_dir1"],
|
|
self.services["random_data"]
|
|
),
|
|
"echo %s > %s/%s/%s/%s" % (
|
|
random_data_1,
|
|
self.services["mount_dir"],
|
|
self.services["sub_dir"],
|
|
self.services["sub_lvl_dir2"],
|
|
self.services["random_data"]
|
|
),
|
|
"sync",
|
|
]
|
|
|
|
for c in cmds:
|
|
self.debug(c)
|
|
result = ssh_client.execute(c)
|
|
self.debug(result)
|
|
|
|
except Exception as e:
|
|
self.fail("SSH failed for VM with IP address: %s" %
|
|
self.virtual_machine.ipaddress)
|
|
|
|
# Unmount the Volume
|
|
cmds = [
|
|
"umount %s" % (self.services["mount_dir"]),
|
|
]
|
|
for c in cmds:
|
|
self.debug(c)
|
|
ssh_client.execute(c)
|
|
|
|
volumes = list_volumes(
|
|
self.apiclient,
|
|
virtualmachineid=self.virtual_machine.id,
|
|
type='ROOT',
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(volumes, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
|
|
volume = volumes[0]
|
|
|
|
#Create a snapshot of volume
|
|
snapshot = Snapshot.create(
|
|
self.apiclient,
|
|
volume.id,
|
|
account=self.account.account.name,
|
|
domainid=self.account.account.domainid
|
|
)
|
|
|
|
self.debug("Snapshot created from volume ID: %s" % volume.id)
|
|
# Generate template from the snapshot
|
|
template = Template.create_from_snapshot(
|
|
self.apiclient,
|
|
snapshot,
|
|
self.services["templates"]
|
|
)
|
|
self.cleanup.append(template)
|
|
self.debug("Template created from snapshot ID: %s" % snapshot.id)
|
|
|
|
# Verify created template
|
|
templates = list_templates(
|
|
self.apiclient,
|
|
templatefilter=\
|
|
self.services["templates"]["templatefilter"],
|
|
id=template.id
|
|
)
|
|
self.assertNotEqual(
|
|
templates,
|
|
None,
|
|
"Check if result exists in list item call"
|
|
)
|
|
|
|
self.assertEqual(
|
|
templates[0].id,
|
|
template.id,
|
|
"Check new template id in list resources call"
|
|
)
|
|
self.debug("Deploying new VM from template: %s" % template.id)
|
|
|
|
# Deploy new virtual machine using template
|
|
new_virtual_machine = VirtualMachine.create(
|
|
self.apiclient,
|
|
self.services["server_without_disk"],
|
|
templateid=template.id,
|
|
accountid=self.account.account.name,
|
|
domainid=self.account.account.domainid,
|
|
serviceofferingid=self.service_offering.id,
|
|
mode=self.services["mode"]
|
|
)
|
|
self.cleanup.append(new_virtual_machine)
|
|
|
|
try:
|
|
#Login to VM & mount directory
|
|
ssh = new_virtual_machine.get_ssh_client()
|
|
|
|
cmds = [
|
|
"mkdir -p %s" % self.services["mount_dir"],
|
|
"mount %s1 %s" % (
|
|
self.services["rootdisk"],
|
|
self.services["mount_dir"]
|
|
)
|
|
]
|
|
|
|
for c in cmds:
|
|
ssh.execute(c)
|
|
|
|
returned_data_0 = ssh.execute("cat %s/%s/%s/%s" % (
|
|
self.services["mount_dir"],
|
|
self.services["sub_dir"],
|
|
self.services["sub_lvl_dir1"],
|
|
self.services["random_data"]
|
|
))
|
|
self.debug(returned_data_0)
|
|
returned_data_1 = ssh.execute("cat %s/%s/%s/%s" % (
|
|
self.services["mount_dir"],
|
|
self.services["sub_dir"],
|
|
self.services["sub_lvl_dir2"],
|
|
self.services["random_data"]
|
|
))
|
|
self.debug(returned_data_1)
|
|
except Exception as e:
|
|
self.fail("SSH failed for VM with IP address: %s" %
|
|
new_virtual_machine.ipaddress)
|
|
#Verify returned data
|
|
self.assertEqual(
|
|
random_data_0,
|
|
returned_data_0[0],
|
|
"Verify newly attached volume contents with existing one"
|
|
)
|
|
self.assertEqual(
|
|
random_data_1,
|
|
returned_data_1[0],
|
|
"Verify newly attached volume contents with existing one"
|
|
)
|
|
# Unmount the volume
|
|
cmds = [
|
|
"umount %s" % (self.services["mount_dir"]),
|
|
]
|
|
try:
|
|
for c in cmds:
|
|
self.debug(c)
|
|
ssh_client.execute(c)
|
|
|
|
except Exception as e:
|
|
self.fail("SSH failed for VM with IP address: %s" %
|
|
new_virtual_machine.ipaddress)
|
|
return
|
|
|
|
class TestCreateVMsnapshotTemplate(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.api_client = super(TestCreateVMsnapshotTemplate, 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)
|
|
|
|
cls.template = get_template(
|
|
cls.api_client,
|
|
cls.zone.id,
|
|
cls.services["ostypeid"]
|
|
)
|
|
cls.services["domainid"] = cls.domain.id
|
|
cls.services["server"]["zoneid"] = cls.zone.id
|
|
|
|
cls.services["template"] = cls.template.id
|
|
|
|
# Create VMs, NAT Rules etc
|
|
cls.account = Account.create(
|
|
cls.api_client,
|
|
cls.services["account"],
|
|
domainid=cls.domain.id
|
|
)
|
|
|
|
cls.services["account"] = cls.account.account.name
|
|
|
|
cls.service_offering = ServiceOffering.create(
|
|
cls.api_client,
|
|
cls.services["service_offering"]
|
|
)
|
|
cls._cleanup = [
|
|
cls.service_offering,
|
|
cls.account,
|
|
]
|
|
return
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
try:
|
|
#Cleanup resources used
|
|
cleanup_resources(cls.api_client, cls._cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
def setUp(self):
|
|
self.apiclient = self.testClient.getApiClient()
|
|
self.dbclient = self.testClient.getDbConnection()
|
|
self.cleanup = []
|
|
return
|
|
|
|
def tearDown(self):
|
|
try:
|
|
#Clean up, terminate the created instance, volumes and snapshots
|
|
cleanup_resources(self.apiclient, self.cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
@attr(speed = "slow")
|
|
@attr(tags = ["advanced", "advancedns"])
|
|
def test_01_createVM_snapshotTemplate(self):
|
|
"""Test create VM, Snapshot and Template
|
|
"""
|
|
# Validate the following
|
|
# 1. Deploy VM using default template, small service offering
|
|
# and small data disk offering.
|
|
# 2. Perform snapshot on the root disk of this VM.
|
|
# 3. Create a template from snapshot.
|
|
# 4. Create a instance from above created template.
|
|
# 5. listSnapshots should list the snapshot that was created.
|
|
# 6. verify that secondary storage NFS share contains the reqd
|
|
# volume under /secondary/snapshots/$accountid/$volumeid/$snapshot_uuid
|
|
# 7. verify backup_snap_id was non null in the `snapshots` table
|
|
# 8. listTemplates() should return the newly created Template,
|
|
# and check for template state as READY"
|
|
# 9. listVirtualMachines() command should return the deployed VM.
|
|
# State of this VM should be Running.
|
|
|
|
#Create Virtual Machine
|
|
self.virtual_machine = VirtualMachine.create(
|
|
self.apiclient,
|
|
self.services["server"],
|
|
templateid=self.template.id,
|
|
accountid=self.account.account.name,
|
|
domainid=self.account.account.domainid,
|
|
serviceofferingid=self.service_offering.id
|
|
)
|
|
self.debug("Created VM with ID: %s" % self.virtual_machine.id)
|
|
# Get the Root disk of VM
|
|
volumes = list_volumes(
|
|
self.apiclient,
|
|
virtualmachineid=self.virtual_machine.id,
|
|
type='ROOT',
|
|
listall=True
|
|
)
|
|
volume = volumes[0]
|
|
|
|
# Create a snapshot from the ROOTDISK
|
|
snapshot = Snapshot.create(self.apiclient, volumes[0].id)
|
|
self.debug("Snapshot created: ID - %s" % snapshot.id)
|
|
self.cleanup.append(snapshot)
|
|
|
|
snapshots = list_snapshots(
|
|
self.apiclient,
|
|
id=snapshot.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(snapshots, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertNotEqual(
|
|
snapshots,
|
|
None,
|
|
"Check if result exists in list snapshots call"
|
|
)
|
|
self.assertEqual(
|
|
snapshots[0].id,
|
|
snapshot.id,
|
|
"Check snapshot id in list resources call"
|
|
)
|
|
self.debug("select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \
|
|
% snapshot.id)
|
|
# Verify backup_snap_id is not NULL
|
|
qresultset = self.dbclient.execute(
|
|
"select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \
|
|
% snapshot.id
|
|
)
|
|
self.assertNotEqual(
|
|
len(qresultset),
|
|
0,
|
|
"Check DB Query result set"
|
|
)
|
|
|
|
qresult = qresultset[0]
|
|
|
|
snapshot_uuid = qresult[0] # backup_snap_id = snapshot UUID
|
|
account_id = qresult[1]
|
|
volume_id = qresult[2]
|
|
|
|
# Generate template from the snapshot
|
|
template = Template.create_from_snapshot(
|
|
self.apiclient,
|
|
snapshot,
|
|
self.services["templates"]
|
|
)
|
|
self.debug("Created template from snapshot: %s" % template.id)
|
|
self.cleanup.append(template)
|
|
|
|
templates = list_templates(
|
|
self.apiclient,
|
|
templatefilter=\
|
|
self.services["templates"]["templatefilter"],
|
|
id=template.id
|
|
)
|
|
|
|
self.assertNotEqual(
|
|
templates,
|
|
None,
|
|
"Check if result exists in list item call"
|
|
)
|
|
|
|
self.assertEqual(
|
|
templates[0].isready,
|
|
True,
|
|
"Check new template state in list templates call"
|
|
)
|
|
|
|
# Deploy new virtual machine using template
|
|
new_virtual_machine = VirtualMachine.create(
|
|
self.apiclient,
|
|
self.services["server"],
|
|
templateid=template.id,
|
|
accountid=self.account.account.name,
|
|
domainid=self.account.account.domainid,
|
|
serviceofferingid=self.service_offering.id
|
|
)
|
|
self.debug("Created VM with ID: %s from template: %s" % (
|
|
new_virtual_machine.id,
|
|
template.id
|
|
))
|
|
self.cleanup.append(new_virtual_machine)
|
|
|
|
# Newly deployed VM should be 'Running'
|
|
virtual_machines = list_virtual_machines(
|
|
self.apiclient,
|
|
id=new_virtual_machine.id,
|
|
account=self.account.account.name,
|
|
domainid=self.account.account.domainid
|
|
)
|
|
self.assertEqual(
|
|
isinstance(virtual_machines, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertNotEqual(
|
|
len(virtual_machines),
|
|
0,
|
|
"Check list virtual machines response"
|
|
)
|
|
for virtual_machine in virtual_machines:
|
|
self.assertEqual(
|
|
virtual_machine.state,
|
|
'Running',
|
|
"Check list VM response for Running state"
|
|
)
|
|
# Get the Secondary Storage details from list Hosts
|
|
hosts = list_hosts(
|
|
self.apiclient,
|
|
type='SecondaryStorage',
|
|
zoneid=self.zone.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(hosts, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
uuids = []
|
|
for host in hosts:
|
|
# hosts[0].name = "nfs://192.168.100.21/export/test"
|
|
parse_url = (host.name).split('/')
|
|
# parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test']
|
|
|
|
# Stripping end ':' from storage type
|
|
storage_type = parse_url[0][:-1]
|
|
# Split IP address and export path from name
|
|
sec_storage_ip = parse_url[2]
|
|
# Sec Storage IP: 192.168.100.21
|
|
if sec_storage_ip[-1] != ":":
|
|
sec_storage_ip = sec_storage_ip + ":"
|
|
|
|
export_path = '/'.join(parse_url[3:])
|
|
# Export path: export/test
|
|
|
|
# Sleep to ensure that snapshot is reflected in sec storage
|
|
time.sleep(self.services["sleep"])
|
|
try:
|
|
# Login to VM to check snapshot present on sec disk
|
|
ssh_client = remoteSSHClient(
|
|
self.services["mgmt_server"]["ipaddress"],
|
|
self.services["mgmt_server"]["port"],
|
|
self.services["mgmt_server"]["username"],
|
|
self.services["mgmt_server"]["password"],
|
|
)
|
|
|
|
cmds = [
|
|
"mkdir -p %s" % self.services["mount_dir"],
|
|
"mount -t %s %s/%s %s" % (
|
|
storage_type,
|
|
sec_storage_ip,
|
|
export_path,
|
|
self.services["mount_dir"]
|
|
),
|
|
"ls %s/snapshots/%s/%s" % (
|
|
self.services["mount_dir"],
|
|
account_id,
|
|
volume_id
|
|
),
|
|
]
|
|
for c in cmds:
|
|
self.debug("command: %s" % c)
|
|
result = ssh_client.execute(c)
|
|
self.debug("Result: %s" % result)
|
|
|
|
except Exception as e:
|
|
self.fail("SSH failed for Management server: %s - %s" %
|
|
(self.services["mgmt_server"]["ipaddress"], e))
|
|
uuids.append(result)
|
|
# Unmount the Sec Storage
|
|
cmds = [
|
|
"umount %s" % (self.services["mount_dir"]),
|
|
]
|
|
try:
|
|
for c in cmds:
|
|
self.debug("command: %s" % c)
|
|
result = ssh_client.execute(c)
|
|
self.debug("Result: %s" % result)
|
|
|
|
except Exception as e:
|
|
self.fail("SSH failed for Management server: %s - %s" %
|
|
(self.services["mgmt_server"]["ipaddress"], e))
|
|
|
|
res = str(uuids)
|
|
self.assertEqual(
|
|
res.count(snapshot_uuid),
|
|
1,
|
|
"Check snapshot UUID in secondary storage and database"
|
|
)
|
|
|
|
return
|
|
|
|
|
|
class TestAccountSnapshotClean(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.api_client = super(TestAccountSnapshotClean, 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["ostypeid"]
|
|
)
|
|
cls.services["server"]["zoneid"] = cls.zone.id
|
|
|
|
cls.services["template"] = template.id
|
|
|
|
# Create VMs, NAT Rules etc
|
|
cls.account = Account.create(
|
|
cls.api_client,
|
|
cls.services["account"],
|
|
domainid=cls.domain.id
|
|
)
|
|
|
|
cls.services["account"] = cls.account.account.name
|
|
|
|
cls.service_offering = ServiceOffering.create(
|
|
cls.api_client,
|
|
cls.services["service_offering"]
|
|
)
|
|
cls.virtual_machine = VirtualMachine.create(
|
|
cls.api_client,
|
|
cls.services["server"],
|
|
templateid=template.id,
|
|
accountid=cls.account.account.name,
|
|
domainid=cls.account.account.domainid,
|
|
serviceofferingid=cls.service_offering.id
|
|
)
|
|
# Get the Root disk of VM
|
|
volumes = list_volumes(
|
|
cls.api_client,
|
|
virtualmachineid=cls.virtual_machine.id,
|
|
type='ROOT',
|
|
listall=True
|
|
)
|
|
volume = volumes[0]
|
|
|
|
# Create a snapshot from the ROOTDISK
|
|
cls.snapshot = Snapshot.create(cls.api_client, volumes[0].id)
|
|
|
|
cls._cleanup = [
|
|
cls.service_offering,
|
|
]
|
|
return
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
try:
|
|
#Cleanup resources used
|
|
cleanup_resources(cls.api_client, cls._cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
def setUp(self):
|
|
self.apiclient = self.testClient.getApiClient()
|
|
self.dbclient = self.testClient.getDbConnection()
|
|
self.cleanup = []
|
|
return
|
|
|
|
def tearDown(self):
|
|
try:
|
|
#Clean up, terminate the created instance, volumes and snapshots
|
|
cleanup_resources(self.apiclient, self.cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
@attr(speed = "slow")
|
|
@attr(tags = ["advanced", "advancedns"])
|
|
def test_02_accountSnapshotClean(self):
|
|
"""Test snapshot cleanup after account deletion
|
|
"""
|
|
# Validate the following
|
|
# 1. listAccounts API should list out the newly created account
|
|
# 2. listVirtualMachines() command should return the deployed VM.
|
|
# State of this VM should be "Running"
|
|
# 3. a)listSnapshots should list the snapshot that was created.
|
|
# b)verify that secondary storage NFS share contains the reqd volume
|
|
# under /secondary/snapshots/$accountid/$volumeid/$snapshot_uuid
|
|
# 4. a)listAccounts should not list account that is deleted
|
|
# b) snapshot image($snapshot_uuid) should be deleted from the
|
|
# /secondary/snapshots/$accountid/$volumeid/
|
|
|
|
accounts = list_accounts(
|
|
self.apiclient,
|
|
id=self.account.account.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(accounts, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertNotEqual(
|
|
len(accounts),
|
|
0,
|
|
"Check list Accounts response"
|
|
)
|
|
|
|
# VM should be in 'Running' state
|
|
virtual_machines = list_virtual_machines(
|
|
self.apiclient,
|
|
id=self.virtual_machine.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(virtual_machines, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertNotEqual(
|
|
len(virtual_machines),
|
|
0,
|
|
"Check list virtual machines response"
|
|
)
|
|
for virtual_machine in virtual_machines:
|
|
self.debug("VM ID: %s, VM state: %s" % (
|
|
virtual_machine.id,
|
|
virtual_machine.state
|
|
))
|
|
self.assertEqual(
|
|
virtual_machine.state,
|
|
'Running',
|
|
"Check list VM response for Running state"
|
|
)
|
|
|
|
# Verify the snapshot was created or not
|
|
snapshots = list_snapshots(
|
|
self.apiclient,
|
|
id=self.snapshot.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(snapshots, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertNotEqual(
|
|
snapshots,
|
|
None,
|
|
"Check if result exists in list snapshots call"
|
|
)
|
|
self.assertEqual(
|
|
snapshots[0].id,
|
|
self.snapshot.id,
|
|
"Check snapshot id in list resources call"
|
|
)
|
|
|
|
# Fetch values from database
|
|
qresultset = self.dbclient.execute(
|
|
"select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \
|
|
% self.snapshot.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(qresultset, list),
|
|
True,
|
|
"Check DB response returns a valid list"
|
|
)
|
|
self.assertNotEqual(
|
|
len(qresultset),
|
|
0,
|
|
"Check DB Query result set"
|
|
)
|
|
|
|
qresult = qresultset[0]
|
|
snapshot_uuid = qresult[0] # backup_snap_id = snapshot UUID
|
|
account_id = qresult[1]
|
|
volume_id = qresult[2]
|
|
|
|
# Get the Secondary Storage details from list Hosts
|
|
hosts = list_hosts(
|
|
self.apiclient,
|
|
type='SecondaryStorage',
|
|
zoneid=self.zone.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(hosts, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
uuids = []
|
|
for host in hosts:
|
|
# hosts[0].name = "nfs://192.168.100.21/export/test"
|
|
parse_url = (host.name).split('/')
|
|
# parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test']
|
|
|
|
# Stripping end ':' from storage type
|
|
storage_type = parse_url[0][:-1]
|
|
# Split IP address and export path from name
|
|
sec_storage_ip = parse_url[2]
|
|
# Sec Storage IP: 192.168.100.21
|
|
|
|
if sec_storage_ip[-1] != ":":
|
|
sec_storage_ip = sec_storage_ip + ":"
|
|
|
|
export_path = '/'.join(parse_url[3:])
|
|
# Export path: export/test
|
|
|
|
# Sleep to ensure that snapshot is reflected in sec storage
|
|
time.sleep(self.services["sleep"])
|
|
try:
|
|
# Login to Secondary storage VM to check snapshot present on sec disk
|
|
ssh_client = remoteSSHClient(
|
|
self.services["mgmt_server"]["ipaddress"],
|
|
self.services["mgmt_server"]["port"],
|
|
self.services["mgmt_server"]["username"],
|
|
self.services["mgmt_server"]["password"],
|
|
)
|
|
|
|
cmds = [
|
|
"mkdir -p %s" % self.services["mount_dir"],
|
|
"mount -t %s %s/%s %s" % (
|
|
storage_type,
|
|
sec_storage_ip,
|
|
export_path,
|
|
self.services["mount_dir"]
|
|
),
|
|
"ls %s/snapshots/%s/%s" % (
|
|
self.services["mount_dir"],
|
|
account_id,
|
|
volume_id
|
|
),
|
|
]
|
|
|
|
for c in cmds:
|
|
self.debug("command: %s" % c)
|
|
result = ssh_client.execute(c)
|
|
self.debug("Result: %s" % result)
|
|
|
|
uuids.append(result)
|
|
|
|
# Unmount the Sec Storage
|
|
cmds = [
|
|
"umount %s" % (self.services["mount_dir"]),
|
|
]
|
|
for c in cmds:
|
|
result = ssh_client.execute(c)
|
|
except Exception as e:
|
|
self.fail("SSH failed for management server: %s - %s" %
|
|
(self.services["mgmt_server"]["ipaddress"], e))
|
|
|
|
res = str(uuids)
|
|
self.assertEqual(
|
|
res.count(snapshot_uuid),
|
|
1,
|
|
"Check snapshot UUID in secondary storage and database"
|
|
)
|
|
|
|
self.debug("Deleting account: %s" % self.account.account.name)
|
|
# Delete account
|
|
self.account.delete(self.apiclient)
|
|
|
|
interval = list_configurations(
|
|
self.apiclient,
|
|
name='account.cleanup.interval'
|
|
)
|
|
self.assertEqual(
|
|
isinstance(interval, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.debug("account.cleanup.interval: %s" % interval[0].value)
|
|
|
|
# Wait for account cleanup interval
|
|
time.sleep(int(interval[0].value) * 2)
|
|
|
|
accounts = list_accounts(
|
|
self.apiclient,
|
|
id=self.account.account.id
|
|
)
|
|
|
|
self.assertEqual(
|
|
accounts,
|
|
None,
|
|
"List accounts should return empty list after account deletion"
|
|
)
|
|
|
|
uuids = []
|
|
for host in hosts:
|
|
# hosts[0].name = "nfs://192.168.100.21/export/test"
|
|
parse_url = (host.name).split('/')
|
|
# parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test']
|
|
|
|
# Stripping end ':' from storage type
|
|
storage_type = parse_url[0][:-1]
|
|
# Split IP address and export path from name
|
|
sec_storage_ip = parse_url[2]
|
|
# Sec Storage IP: 192.168.100.21
|
|
|
|
if sec_storage_ip[-1] != ":":
|
|
sec_storage_ip = sec_storage_ip + ":"
|
|
|
|
export_path = '/'.join(parse_url[3:])
|
|
# Export path: export/test
|
|
|
|
try:
|
|
cmds = [
|
|
"mount -t %s %s/%s %s" % (
|
|
storage_type,
|
|
sec_storage_ip,
|
|
export_path,
|
|
self.services["mount_dir"]
|
|
),
|
|
"ls %s/snapshots/%s/%s" % (
|
|
self.services["mount_dir"],
|
|
account_id,
|
|
volume_id
|
|
),
|
|
]
|
|
|
|
for c in cmds:
|
|
self.debug("command: %s" % c)
|
|
result = ssh_client.execute(c)
|
|
self.debug("Result: %s" % result)
|
|
|
|
uuids.append(result)
|
|
# Unmount the Sec Storage
|
|
cmds = [
|
|
"umount %s" % (self.services["mount_dir"]),
|
|
]
|
|
for c in cmds:
|
|
self.debug("command: %s" % c)
|
|
result = ssh_client.execute(c)
|
|
self.debug("Result: %s" % result)
|
|
|
|
except Exception as e:
|
|
self.fail("SSH failed for management server: %s - %s" %
|
|
(self.services["mgmt_server"]["ipaddress"], e))
|
|
|
|
res = str(uuids)
|
|
self.assertNotEqual(
|
|
res.count(snapshot_uuid),
|
|
1,
|
|
"Check snapshot UUID in secondary storage and database"
|
|
)
|
|
return
|
|
|
|
|
|
class TestSnapshotDetachedDisk(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.api_client = super(TestSnapshotDetachedDisk, 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)
|
|
|
|
cls.disk_offering = DiskOffering.create(
|
|
cls.api_client,
|
|
cls.services["disk_offering"]
|
|
)
|
|
template = get_template(
|
|
cls.api_client,
|
|
cls.zone.id,
|
|
cls.services["ostypeid"]
|
|
)
|
|
cls.services["server"]["zoneid"] = cls.zone.id
|
|
cls.services["server"]["diskoffering"] = cls.disk_offering.id
|
|
|
|
cls.services["template"] = template.id
|
|
|
|
# Create VMs, NAT Rules etc
|
|
cls.account = Account.create(
|
|
cls.api_client,
|
|
cls.services["account"],
|
|
domainid=cls.domain.id
|
|
)
|
|
|
|
cls.services["account"] = cls.account.account.name
|
|
|
|
cls.service_offering = ServiceOffering.create(
|
|
cls.api_client,
|
|
cls.services["service_offering"]
|
|
)
|
|
cls.virtual_machine = VirtualMachine.create(
|
|
cls.api_client,
|
|
cls.services["server"],
|
|
templateid=template.id,
|
|
accountid=cls.account.account.name,
|
|
domainid=cls.account.account.domainid,
|
|
serviceofferingid=cls.service_offering.id,
|
|
mode=cls.services["mode"]
|
|
)
|
|
cls._cleanup = [
|
|
cls.service_offering,
|
|
cls.disk_offering,
|
|
cls.account,
|
|
]
|
|
return
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
try:
|
|
#Cleanup resources used
|
|
cleanup_resources(cls.api_client, cls._cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
def setUp(self):
|
|
self.apiclient = self.testClient.getApiClient()
|
|
self.dbclient = self.testClient.getDbConnection()
|
|
self.cleanup = []
|
|
return
|
|
|
|
def tearDown(self):
|
|
try:
|
|
#Clean up, terminate the created instance, volumes and snapshots
|
|
cleanup_resources(self.apiclient, self.cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
@attr(speed = "slow")
|
|
@attr(tags = ["advanced", "advancedns"])
|
|
def test_03_snapshot_detachedDisk(self):
|
|
"""Test snapshot from detached disk
|
|
"""
|
|
# Validate the following
|
|
# 1. login in VM and write some data on data disk(use fdisk to
|
|
# partition datadisk,fdisk /dev/sdb, and make filesystem using
|
|
# mkfs.ext3)
|
|
# 2. Detach the data disk and write some data on data disk
|
|
# 3. perform the snapshot on the detached volume
|
|
# 4. listvolumes with VM id shouldn't show the detached volume
|
|
# 5. listSnapshots should list the snapshot that was created
|
|
# 6. verify that secondary storage NFS share contains the reqd volume
|
|
# under /secondary/snapshots/$accountid/$volumeid/$snapshot_uuid
|
|
# 7. verify backup_snap_id was non null in the `snapshots` table
|
|
|
|
volumes = list_volumes(
|
|
self.apiclient,
|
|
virtualmachineid=self.virtual_machine.id,
|
|
type='DATADISK',
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(volumes, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
volume = volumes[0]
|
|
random_data_0 = random_gen(100)
|
|
random_data_1 = random_gen(100)
|
|
try:
|
|
ssh_client = self.virtual_machine.get_ssh_client()
|
|
|
|
#Format partition using ext3
|
|
format_volume_to_ext3(
|
|
ssh_client,
|
|
self.services["diskdevice"]
|
|
)
|
|
cmds = [
|
|
"mkdir -p %s" % self.services["mount_dir"],
|
|
"mount %s1 %s" % (
|
|
self.services["diskdevice"],
|
|
self.services["mount_dir"]
|
|
),
|
|
"pushd %s" % self.services["mount_dir"],
|
|
"mkdir -p %s/{%s,%s} " % (
|
|
self.services["sub_dir"],
|
|
self.services["sub_lvl_dir1"],
|
|
self.services["sub_lvl_dir2"]
|
|
),
|
|
"echo %s > %s/%s/%s" % (
|
|
random_data_0,
|
|
self.services["sub_dir"],
|
|
self.services["sub_lvl_dir1"],
|
|
self.services["random_data"]
|
|
),
|
|
"echo %s > %s/%s/%s" % (
|
|
random_data_1,
|
|
self.services["sub_dir"],
|
|
self.services["sub_lvl_dir2"],
|
|
self.services["random_data"]
|
|
),
|
|
"sync",
|
|
]
|
|
for c in cmds:
|
|
self.debug(ssh_client.execute(c))
|
|
|
|
#detach volume from VM
|
|
cmd = detachVolume.detachVolumeCmd()
|
|
cmd.id = volume.id
|
|
self.apiclient.detachVolume(cmd)
|
|
|
|
#Create snapshot from detached volume
|
|
snapshot = Snapshot.create(self.apiclient, volume.id)
|
|
self.cleanup.append(snapshot)
|
|
|
|
volumes = list_volumes(
|
|
self.apiclient,
|
|
virtualmachineid=self.virtual_machine.id,
|
|
type='DATADISK',
|
|
listall=True
|
|
)
|
|
|
|
self.assertEqual(
|
|
volumes,
|
|
None,
|
|
"Check Volume is detached"
|
|
)
|
|
|
|
# Verify the snapshot was created or not
|
|
snapshots = list_snapshots(
|
|
self.apiclient,
|
|
id=snapshot.id
|
|
)
|
|
self.assertNotEqual(
|
|
snapshots,
|
|
None,
|
|
"Check if result exists in list snapshots call"
|
|
)
|
|
self.assertEqual(
|
|
snapshots[0].id,
|
|
snapshot.id,
|
|
"Check snapshot id in list resources call"
|
|
)
|
|
except Exception as e:
|
|
self.fail("SSH failed for VM with IP: %s - %s" %
|
|
(self.virtual_machine.ipaddress, e))
|
|
|
|
# Fetch values from database
|
|
qresultset = self.dbclient.execute(
|
|
"select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \
|
|
% snapshot.id
|
|
)
|
|
self.assertNotEqual(
|
|
len(qresultset),
|
|
0,
|
|
"Check DB Query result set"
|
|
)
|
|
|
|
qresult = qresultset[0]
|
|
snapshot_uuid = qresult[0] # backup_snap_id = snapshot UUID
|
|
account_id = qresult[1]
|
|
volume_id = qresult[2]
|
|
|
|
self.assertNotEqual(
|
|
str(qresult[0]),
|
|
'NULL',
|
|
"Check if backup_snap_id is not null"
|
|
)
|
|
|
|
# Get the Secondary Storage details from list Hosts
|
|
hosts = list_hosts(
|
|
self.apiclient,
|
|
type='SecondaryStorage',
|
|
zoneid=self.zone.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(hosts, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
uuids = []
|
|
for host in hosts:
|
|
# hosts[0].name = "nfs://192.168.100.21/export/test"
|
|
parse_url = (host.name).split('/')
|
|
# parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test']
|
|
|
|
# Stripping end ':' from storage type
|
|
storage_type = parse_url[0][:-1]
|
|
|
|
# Split IP address and export path from name
|
|
sec_storage_ip = parse_url[2]
|
|
# Sec Storage IP: 192.168.100.21
|
|
|
|
if sec_storage_ip[-1] != ":":
|
|
sec_storage_ip = sec_storage_ip + ":"
|
|
|
|
export_path = '/'.join(parse_url[3:])
|
|
# Export path: export/test
|
|
|
|
# Sleep to ensure that snapshot is reflected in sec storage
|
|
time.sleep(self.services["sleep"])
|
|
try:
|
|
# Login to Management server to check snapshot present on
|
|
# sec disk
|
|
ssh_client = remoteSSHClient(
|
|
self.services["mgmt_server"]["ipaddress"],
|
|
self.services["mgmt_server"]["port"],
|
|
self.services["mgmt_server"]["username"],
|
|
self.services["mgmt_server"]["password"],
|
|
)
|
|
|
|
cmds = [
|
|
"mkdir -p %s" % self.services["mount_dir"],
|
|
"mount -t %s %s/%s %s" % (
|
|
storage_type,
|
|
sec_storage_ip,
|
|
export_path,
|
|
self.services["mount_dir"]
|
|
),
|
|
"ls %s/snapshots/%s/%s" % (
|
|
self.services["mount_dir"],
|
|
account_id,
|
|
volume_id
|
|
),
|
|
]
|
|
|
|
for c in cmds:
|
|
result = ssh_client.execute(c)
|
|
|
|
uuids.append(result)
|
|
# Unmount the Sec Storage
|
|
cmds = [
|
|
"umount %s" % (self.services["mount_dir"]),
|
|
]
|
|
for c in cmds:
|
|
result = ssh_client.execute(c)
|
|
except Exception as e:
|
|
self.fail("SSH failed for management server: %s - %s" %
|
|
(self.services["mgmt_server"]["ipaddress"], e))
|
|
|
|
res = str(uuids)
|
|
self.assertEqual(
|
|
res.count(snapshot_uuid),
|
|
1,
|
|
"Check snapshot UUID in secondary storage and database"
|
|
)
|
|
return
|
|
|
|
|
|
class TestSnapshotLimit(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.api_client = super(TestSnapshotLimit, 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["ostypeid"]
|
|
)
|
|
cls.services["server"]["zoneid"] = cls.zone.id
|
|
|
|
cls.services["template"] = template.id
|
|
|
|
# Create VMs, NAT Rules etc
|
|
cls.account = Account.create(
|
|
cls.api_client,
|
|
cls.services["account"],
|
|
domainid=cls.domain.id
|
|
)
|
|
|
|
cls.services["account"] = cls.account.account.name
|
|
|
|
cls.service_offering = ServiceOffering.create(
|
|
cls.api_client,
|
|
cls.services["service_offering"]
|
|
)
|
|
cls.virtual_machine = VirtualMachine.create(
|
|
cls.api_client,
|
|
cls.services["server"],
|
|
templateid=template.id,
|
|
accountid=cls.account.account.name,
|
|
domainid=cls.account.account.domainid,
|
|
serviceofferingid=cls.service_offering.id
|
|
)
|
|
cls._cleanup = [
|
|
cls.service_offering,
|
|
cls.account,
|
|
]
|
|
return
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
try:
|
|
#Cleanup resources used
|
|
cleanup_resources(cls.api_client, cls._cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
def setUp(self):
|
|
self.apiclient = self.testClient.getApiClient()
|
|
self.dbclient = self.testClient.getDbConnection()
|
|
self.cleanup = []
|
|
return
|
|
|
|
def tearDown(self):
|
|
try:
|
|
#Clean up, terminate the created instance, volumes and snapshots
|
|
cleanup_resources(self.apiclient, self.cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
@attr(speed = "slow")
|
|
@attr(tags = ["advanced", "advancedns"])
|
|
def test_04_snapshot_limit(self):
|
|
"""Test snapshot limit in snapshot policies
|
|
"""
|
|
# Validate the following
|
|
# 1. Perform hourly recurring snapshot on the root disk of VM and keep
|
|
# the maxsnapshots as 1
|
|
# 2. listSnapshots should list the snapshot that was created
|
|
# snapshot folder in secondary storage should contain only one
|
|
# snapshot image(/secondary/snapshots/$accountid/$volumeid/)
|
|
|
|
# Get the Root disk of VM
|
|
volumes = list_volumes(
|
|
self.apiclient,
|
|
virtualmachineid=self.virtual_machine.id,
|
|
type='ROOT',
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(volumes, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
volume = volumes[0]
|
|
|
|
# Create a snapshot policy
|
|
recurring_snapshot = SnapshotPolicy.create(
|
|
self.apiclient,
|
|
volume.id,
|
|
self.services["recurring_snapshot"]
|
|
)
|
|
self.cleanup.append(recurring_snapshot)
|
|
|
|
snapshot_policy = list_snapshot_policy(
|
|
self.apiclient,
|
|
id=recurring_snapshot.id,
|
|
volumeid=volume.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(snapshot_policy, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
|
|
self.assertNotEqual(
|
|
snapshot_policy,
|
|
None,
|
|
"Check if result exists in list item call"
|
|
)
|
|
|
|
self.assertEqual(
|
|
snapshot_policy[0].id,
|
|
recurring_snapshot.id,
|
|
"Check recurring snapshot id in list resources call"
|
|
)
|
|
self.assertEqual(
|
|
snapshot_policy[0].maxsnaps,
|
|
self.services["recurring_snapshot"]["maxsnaps"],
|
|
"Check interval type in list resources call"
|
|
)
|
|
# Sleep for (maxsnaps+1) hours to verify
|
|
# only maxsnaps snapshots are retained
|
|
time.sleep(
|
|
(self.services["recurring_snapshot"]["maxsnaps"]) * 3600
|
|
)
|
|
|
|
# Verify the snapshot was created or not
|
|
snapshots = list_snapshots(
|
|
self.apiclient,
|
|
volumeid=volume.id,
|
|
intervaltype=\
|
|
self.services["recurring_snapshot"]["intervaltype"],
|
|
snapshottype='RECURRING',
|
|
listall=True
|
|
)
|
|
|
|
self.assertEqual(
|
|
isinstance(snapshots, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertEqual(
|
|
len(snapshots),
|
|
self.services["recurring_snapshot"]["maxsnaps"],
|
|
"Check maximum number of recurring snapshots retained"
|
|
)
|
|
snapshot = snapshots[0]
|
|
# Sleep to ensure that snapshot is reflected in sec storage
|
|
time.sleep(self.services["sleep"])
|
|
|
|
# Fetch values from database
|
|
qresultset = self.dbclient.execute(
|
|
"select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \
|
|
% snapshot.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(qresultset, list),
|
|
True,
|
|
"Check DBQuery returns a valid list"
|
|
)
|
|
self.assertNotEqual(
|
|
len(qresultset),
|
|
0,
|
|
"Check DB Query result set"
|
|
)
|
|
|
|
qresult = qresultset[0]
|
|
snapshot_uuid = qresult[0] # backup_snap_id = snapshot UUID
|
|
account_id = qresult[1]
|
|
volume_id = qresult[2]
|
|
|
|
# Get the Secondary Storage details from list Hosts
|
|
hosts = list_hosts(
|
|
self.apiclient,
|
|
type='SecondaryStorage',
|
|
zoneid=self.zone.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(hosts, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
uuids = []
|
|
for host in hosts:
|
|
# hosts[0].name = "nfs://192.168.100.21/export/test"
|
|
parse_url = (host.name).split('/')
|
|
# parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test']
|
|
|
|
# Stripping end ':' from storage type
|
|
storage_type = parse_url[0][:-1]
|
|
# Split IP address and export path from name
|
|
sec_storage_ip = parse_url[2]
|
|
# Sec Storage IP: 192.168.100.21
|
|
|
|
if sec_storage_ip[-1] != ":":
|
|
sec_storage_ip = sec_storage_ip + ":"
|
|
|
|
export_path = '/'.join(parse_url[3:])
|
|
# Export path: export/test
|
|
try:
|
|
# Login to VM to check snapshot present on sec disk
|
|
ssh_client = remoteSSHClient(
|
|
self.services["mgmt_server"]["ipaddress"],
|
|
self.services["mgmt_server"]["port"],
|
|
self.services["mgmt_server"]["username"],
|
|
self.services["mgmt_server"]["password"],
|
|
)
|
|
|
|
cmds = [
|
|
"mkdir -p %s" % self.services["mount_dir"],
|
|
"mount -t %s %s/%s %s" % (
|
|
storage_type,
|
|
sec_storage_ip,
|
|
export_path,
|
|
self.services["mount_dir"]
|
|
),
|
|
"ls %s/snapshots/%s/%s" % (
|
|
self.services["mount_dir"],
|
|
account_id,
|
|
volume_id
|
|
),
|
|
]
|
|
|
|
for c in cmds:
|
|
result = ssh_client.execute(c)
|
|
|
|
uuids.append(result)
|
|
|
|
# Unmount the Sec Storage
|
|
cmds = [
|
|
"umount %s" % (self.services["mount_dir"]),
|
|
]
|
|
for c in cmds:
|
|
result = ssh_client.execute(c)
|
|
except Exception as e:
|
|
raise Exception(
|
|
"SSH access failed for management server: %s - %s" %
|
|
(self.services["mgmt_server"]["ipaddress"], e))
|
|
|
|
res = str(uuids)
|
|
self.assertEqual(
|
|
res.count(snapshot_uuid),
|
|
1,
|
|
"Check snapshot UUID in secondary storage and database"
|
|
)
|
|
return
|
|
|
|
|
|
class TestSnapshotEvents(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.api_client = super(TestSnapshotEvents, 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["ostypeid"]
|
|
)
|
|
cls.services["server"]["zoneid"] = cls.zone.id
|
|
|
|
cls.services["template"] = template.id
|
|
|
|
# Create VMs, NAT Rules etc
|
|
cls.account = Account.create(
|
|
cls.api_client,
|
|
cls.services["account"],
|
|
domainid=cls.domain.id
|
|
)
|
|
|
|
cls.services["account"] = cls.account.account.name
|
|
|
|
cls.service_offering = ServiceOffering.create(
|
|
cls.api_client,
|
|
cls.services["service_offering"]
|
|
)
|
|
cls.virtual_machine = VirtualMachine.create(
|
|
cls.api_client,
|
|
cls.services["server"],
|
|
templateid=template.id,
|
|
accountid=cls.account.account.name,
|
|
domainid=cls.account.account.domainid,
|
|
serviceofferingid=cls.service_offering.id
|
|
)
|
|
|
|
cls._cleanup = [
|
|
cls.service_offering,
|
|
cls.account,
|
|
]
|
|
return
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
try:
|
|
#Cleanup resources used
|
|
cleanup_resources(cls.api_client, cls._cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
def setUp(self):
|
|
self.apiclient = self.testClient.getApiClient()
|
|
self.dbclient = self.testClient.getDbConnection()
|
|
self.cleanup = []
|
|
return
|
|
|
|
def tearDown(self):
|
|
try:
|
|
#Clean up, terminate the created instance, volumes and snapshots
|
|
cleanup_resources(self.apiclient, self.cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
@attr(speed = "slow")
|
|
@attr(tags = ["advanced", "advancedns"])
|
|
def test_05_snapshot_events(self):
|
|
"""Test snapshot events
|
|
"""
|
|
# Validate the following
|
|
# 1. Perform snapshot on the root disk of this VM and check the events/alerts.
|
|
# 2. delete the snapshots and check the events/alerts
|
|
# 3. listEvents() shows created/deleted snapshot events
|
|
|
|
# Get the Root disk of VM
|
|
volumes = list_volumes(
|
|
self.apiclient,
|
|
virtualmachineid=self.virtual_machine.id,
|
|
type='ROOT',
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(volumes, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
volume = volumes[0]
|
|
|
|
# Create a snapshot from the ROOTDISK
|
|
snapshot = Snapshot.create(self.apiclient, volumes[0].id)
|
|
self.debug("Snapshot created with ID: %s" % snapshot.id)
|
|
|
|
snapshots = list_snapshots(
|
|
self.apiclient,
|
|
id=snapshot.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(snapshots, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertNotEqual(
|
|
snapshots,
|
|
None,
|
|
"Check if result exists in list snapshots call"
|
|
)
|
|
self.assertEqual(
|
|
snapshots[0].id,
|
|
snapshot.id,
|
|
"Check snapshot id in list resources call"
|
|
)
|
|
snapshot.delete(self.apiclient)
|
|
|
|
# Sleep to ensure that snapshot is deleted properly
|
|
time.sleep(self.services["sleep"])
|
|
events = list_events(
|
|
self.apiclient,
|
|
account=self.account.account.name,
|
|
domainid=self.account.account.domainid,
|
|
type='SNAPSHOT.DELETE'
|
|
)
|
|
self.assertEqual(
|
|
isinstance(events, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertNotEqual(
|
|
events,
|
|
None,
|
|
"Check if event exists in list events call"
|
|
)
|
|
self.assertIn(
|
|
events[0].state,
|
|
['Completed', 'Scheduled'],
|
|
"Check events state in list events call"
|
|
)
|
|
return
|