mirror of
https://github.com/apache/cloudstack
synced 2026-08-05 18:37:13 +00:00
This PR aligns the use of terminology, renaming VM / virtual machine references to 'Instance' and also capitalising the terms Templates, Network, Snapshot, User, Account in CloudStack APIs, error and log messages, events, tooltips, etc. Many typos, grammar and spelling mistakes were fixed, also terms like IPv4, VPN, VPC, etc. were properly capitalised. Some error messages were cleaned for better readability. The test cases, expecting some exception strings were adjusted accordingly. Here is the wiki page, describing the changes in details: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Object+Naming+and+Title+Case+Convention --------- Co-authored-by: Manoj Kumar <manojkr.itbhu@gmail.com> Co-authored-by: Harikrishna <harikrishna.patnala@gmail.com>
1780 lines
67 KiB
Python
1780 lines
67 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 Browser Based Upload Volumes
|
|
"""
|
|
# Import Local Modules
|
|
|
|
import marvin
|
|
from nose.plugins.attrib import attr
|
|
from marvin.cloudstackTestCase import cloudstackTestCase
|
|
import unittest
|
|
from marvin.cloudstackAPI import *
|
|
from marvin.lib.utils import *
|
|
from marvin.lib.base import *
|
|
from marvin.lib.common import *
|
|
from marvin.codes import FAILED
|
|
|
|
import requests
|
|
import random
|
|
import string
|
|
import time
|
|
_multiprocess_shared_ = True
|
|
|
|
class TestBrowseUploadVolume(cloudstackTestCase):
|
|
|
|
"""
|
|
Testing Browse Upload Volume Feature
|
|
"""
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.testClient = super(TestBrowseUploadVolume,cls).getClsTestClient()
|
|
#print cls.testClient.getParsedTestDataConfig()
|
|
cls.testdata = cls.testClient.getParsedTestDataConfig()
|
|
cls.apiclient = cls.testClient.getApiClient()
|
|
cls.hypervisor = cls.testClient.getHypervisorInfo()
|
|
cls._cleanup = []
|
|
cls.domain = get_domain(cls.apiclient)
|
|
cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
|
|
cls.unsupportedHypervisor = False
|
|
hosts = list_hosts(
|
|
cls.apiclient,
|
|
type="Routing"
|
|
)
|
|
|
|
if cls.hypervisor.lower() in ['lxc']:
|
|
# Template creation from root volume is not supported in LXC
|
|
cls.unsupportedHypervisor = True
|
|
return
|
|
|
|
if hosts is None:
|
|
raise unittest.SkipTest(
|
|
"There are no hypervisor's available.Check listhosts response")
|
|
|
|
cls.account = Account.create(
|
|
cls.apiclient,
|
|
cls.testdata["account"],
|
|
domainid=cls.domain.id
|
|
)
|
|
cls._cleanup.append(cls.account)
|
|
|
|
cls.template = get_template(
|
|
cls.apiclient,
|
|
cls.zone.id)
|
|
|
|
if cls.template == FAILED:
|
|
raise unittest.SkipTest(
|
|
"Check for default cent OS template readiness ")
|
|
|
|
cls.service_offering = ServiceOffering.create(
|
|
cls.apiclient,
|
|
cls.testdata["service_offering"]
|
|
)
|
|
cls._cleanup.append(cls.service_offering)
|
|
cls.disk_offering = DiskOffering.create(
|
|
cls.apiclient,
|
|
cls.testdata["resized_disk_offering"],
|
|
custom=True
|
|
)
|
|
cls._cleanup.append(cls.disk_offering)
|
|
cls.project = Project.create(
|
|
cls.apiclient,
|
|
cls.testdata["project"],
|
|
account=cls.account.name,
|
|
domainid=cls.account.domainid
|
|
)
|
|
cls._cleanup.append(cls.project)
|
|
|
|
def setUp(self):
|
|
|
|
if "kvm" in self.hypervisor.lower():
|
|
self.test_template = registerTemplate.registerTemplateCmd()
|
|
self.test_template = registerTemplate.registerTemplateCmd()
|
|
self.test_template.checksum = "{SHA-1}" + "bf580a13f791d86acf3449a7b457a91a14389264"
|
|
self.test_template.hypervisor = self.hypervisor
|
|
self.test_template.zoneid = self.zone.id
|
|
self.test_template.name = 'test sha-1'
|
|
self.test_template.displaytext = 'test sha-1'
|
|
self.test_template.url = "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-kvm.qcow2.bz2"
|
|
self.test_template.format = "QCOW2"
|
|
self.test_template.ostypeid = self.getOsType("Other Linux (64-bit)")
|
|
self.md5 = "ada77653dcf1e59495a9e1ac670ad95f"
|
|
self.sha256 = "0efc03633f2b8f5db08acbcc5dc1be9028572dfd8f1c6c8ea663f0ef94b458c5"
|
|
|
|
if "vmware" in self.hypervisor.lower():
|
|
self.test_template = registerTemplate.registerTemplateCmd()
|
|
self.test_template = registerTemplate.registerTemplateCmd()
|
|
self.test_template.checksum = "{SHA-1}" + "b25d404de8335b4348ff01e49a95b403c90df466"
|
|
self.test_template.hypervisor = self.hypervisor
|
|
self.test_template.zoneid = self.zone.id
|
|
self.test_template.name = 'test sha-2333'
|
|
self.test_template.displaytext = 'test sha-1'
|
|
self.test_template.url = "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-vmware.ova"
|
|
self.test_template.format = "OVA"
|
|
self.test_template.ostypeid = self.getOsType(self, "Other Linux (64-bit)")
|
|
self.md5 = "d6d97389b129c7d898710195510bf4fb"
|
|
self.sha256 = "f57b59f118ab59284a70d6c63229d1de8f2d69bffc5a82b773d6c47e769c12d9"
|
|
|
|
if "xen" in self.hypervisor.lower():
|
|
self.test_template = registerTemplate.registerTemplateCmd()
|
|
self.test_template = registerTemplate.registerTemplateCmd()
|
|
self.test_template.checksum = "{SHA-1}" + "427fad501d0d8a1d63b8600a9a469fbf91191314"
|
|
self.test_template.hypervisor = self.hypervisor
|
|
self.test_template.zoneid = self.zone.id
|
|
self.test_template.name = 'test sha-2333'
|
|
self.test_template.displaytext = 'test sha-1'
|
|
self.test_template.url = "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-xen.vhd.bz2"
|
|
self.test_template.format = "VHD"
|
|
self.test_template.ostypeid = self.getOsType("Other Linux (64-bit)")
|
|
self.md5 = "54ebc933e6e07ae58c0dc97dfd37c824"
|
|
self.sha256 = "bddd9876021d33df9792b71ae4b776598680ac68ecf55e9d9af33c80904cc1f3"
|
|
|
|
if self.unsupportedHypervisor:
|
|
self.skipTest("Skipping test because unsupported hypervisor\
|
|
%s" % self.hypervisor)
|
|
|
|
self.cleanup = []
|
|
|
|
def getOsType(self, param):
|
|
cmd = listOsTypes.listOsTypesCmd()
|
|
cmd.description = param
|
|
return self.apiclient.listOsTypes(cmd)[0].id
|
|
|
|
def __verify_values(self, expected_vals, actual_vals):
|
|
|
|
return_flag = True
|
|
|
|
if len(expected_vals) != len(actual_vals):
|
|
return False
|
|
|
|
keys = list(expected_vals.keys())
|
|
for i in range(0, len(expected_vals)):
|
|
exp_val = expected_vals[keys[i]]
|
|
act_val = actual_vals[keys[i]]
|
|
if exp_val == act_val:
|
|
return_flag = return_flag and True
|
|
else:
|
|
return_flag = return_flag and False
|
|
self.debug(
|
|
"expected Value: %s, is not matching with actual value:\
|
|
%s" %
|
|
(exp_val, act_val))
|
|
return return_flag
|
|
|
|
def validate_uploaded_template(self, apiclient, template_id, retries=70, interval=5):
|
|
"""Check if template download will finish in 1 minute"""
|
|
while retries > -1:
|
|
time.sleep(interval)
|
|
template_response = Template.list(
|
|
apiclient,
|
|
id=template_id,
|
|
zoneid=self.zone.id,
|
|
templatefilter='self'
|
|
)
|
|
|
|
if isinstance(template_response, list):
|
|
template = template_response[0]
|
|
if not hasattr(template, 'status') or not template or not template.status:
|
|
retries = retries - 1
|
|
continue
|
|
|
|
# If template is ready,
|
|
# template.status = Download Complete
|
|
# Downloading - x% Downloaded
|
|
# if Failed
|
|
# Error - Any other string
|
|
if 'Failed' in template.status:
|
|
raise Exception(
|
|
"Failed to download template: status - %s" %
|
|
template.status)
|
|
|
|
elif template.status == 'Download Complete' and template.isready:
|
|
return
|
|
|
|
elif 'Downloaded' in template.status:
|
|
retries = retries - 1
|
|
continue
|
|
|
|
elif 'Installing' not in template.status:
|
|
if retries >= 0:
|
|
retries = retries - 1
|
|
continue
|
|
raise Exception(
|
|
"Error in downloading template: status - %s" %
|
|
template.status)
|
|
|
|
else:
|
|
retries = retries - 1
|
|
raise Exception("Template download failed exception.")
|
|
|
|
def gettemplatelimts(self):
|
|
|
|
totalresourcelist=Account.list(
|
|
self.apiclient,
|
|
id=self.account.id
|
|
)
|
|
totaltemplates=totalresourcelist[0].templatetotal
|
|
|
|
return(totaltemplates)
|
|
|
|
def getstoragelimits(self, rtype):
|
|
|
|
cmd=updateResourceCount.updateResourceCountCmd()
|
|
cmd.account=self.account.name
|
|
cmd.domainid=self.domain.id
|
|
cmd.resourcetype=rtype
|
|
|
|
response=self.apiclient.updateResourceCount(cmd)
|
|
|
|
totalstorage=response[0].resourcecount
|
|
|
|
return(totalstorage)
|
|
|
|
def browse_upload_template(self):
|
|
cmd = getUploadParamsForTemplate.getUploadParamsForTemplateCmd()
|
|
cmd.zoneid = self.test_template.zoneid
|
|
cmd.format = self.test_template.format
|
|
cmd.name=self.test_template.name + self.account.name + (random.choice(string.ascii_uppercase))
|
|
cmd.account=self.account.name
|
|
cmd.domainid=self.domain.id
|
|
cmd.displaytext=self.test_template.name + self.account.name + (random.choice(string.ascii_uppercase))
|
|
cmd.hypervisor=self.test_template.hypervisor
|
|
cmd.ostypeid=self.test_template.ostypeid
|
|
#cmd.isdynamicallyscalable="false"
|
|
#cmd.type="template"
|
|
getuploadparamsresponse=self.apiclient.getUploadParamsForTemplate(cmd)
|
|
|
|
signt=getuploadparamsresponse.signature
|
|
posturl=getuploadparamsresponse.postURL
|
|
metadata=getuploadparamsresponse.metadata
|
|
expiredata=getuploadparamsresponse.expires
|
|
#url = 'http://10.147.28.7/templates/rajani-thin-volume.vhd'
|
|
url=self.test_template.url
|
|
|
|
uploadfile = url.split('/')[-1]
|
|
r = requests.get(url, stream=True)
|
|
with open(uploadfile, 'wb') as f:
|
|
for chunk in r.iter_content(chunk_size=1024):
|
|
if chunk: # filter out keep-alive new chunks
|
|
f.write(chunk)
|
|
f.flush()
|
|
|
|
#uploadfile='rajani-thin-volume.vhd'
|
|
|
|
#files={'file':('rajani-thin-volume.vhd',open(uploadfile,'rb'),'application/octet-stream')}
|
|
|
|
#headers={'x-signature':signt,'x-metadata':metadata,'x-expires':expiredata}
|
|
|
|
files={'file':(uploadfile,open(uploadfile,'rb'),'application/octet-stream')}
|
|
|
|
headers={'x-signature':signt,'x-metadata':metadata,'x-expires':expiredata}
|
|
|
|
results = requests.post(posturl,files=files,headers=headers,verify=False)
|
|
|
|
print(results.status_code)
|
|
if results.status_code !=200:
|
|
self.fail("Upload is not fine")
|
|
|
|
self.validate_uploaded_template(self.apiclient, getuploadparamsresponse.id)
|
|
|
|
return(getuploadparamsresponse)
|
|
|
|
def browse_upload_template_with_out_zoneid(self):
|
|
|
|
cmd = getUploadParamsForTemplate.getUploadParamsForTemplateCmd()
|
|
cmd.format = self.test_template.format
|
|
cmd.name=self.test_template.name+self.account.name+(random.choice(string.ascii_uppercase))
|
|
cmd.account=self.account.name
|
|
cmd.domainid=self.domain.id
|
|
cmd.displaytext=self.test_template.name+self.account.name+(random.choice(string.ascii_uppercase))
|
|
cmd.hypervisor=self.test_template.hypervisor
|
|
cmd.ostypeid=self.test_template.ostypeid
|
|
|
|
success= False
|
|
try:
|
|
getuploadparamsresponse=self.apiclient.getUploadParamsForTemplate(cmd)
|
|
except Exception as ex:
|
|
if "Invalid Parameter" in str(ex):
|
|
success = True
|
|
self.assertEqual(
|
|
success,
|
|
True,
|
|
"Upload Template - verify upload Template API request is handled without mandatory params - zoneid ")
|
|
|
|
return
|
|
|
|
def browse_upload_template_with_out_ostypeid(self):
|
|
|
|
|
|
cmd = getUploadParamsForTemplate.getUploadParamsForTemplateCmd()
|
|
cmd.zoneid = self.zone.id
|
|
cmd.format = self.test_template.format
|
|
cmd.name=self.test_template.name+self.account.name+(random.choice(string.ascii_uppercase))
|
|
cmd.account=self.account.name
|
|
cmd.domainid=self.domain.id
|
|
cmd.displaytext=self.test_template.name+self.account.name+(random.choice(string.ascii_uppercase))
|
|
cmd.hypervisor=self.test_template.hypervisor
|
|
|
|
success= False
|
|
try:
|
|
getuploadparamsresponse=self.apiclient.getUploadParamsForTemplate(cmd)
|
|
except Exception as ex:
|
|
if "Invalid Parameter" in str(ex):
|
|
success = True
|
|
self.assertEqual(
|
|
success,
|
|
True,
|
|
"Upload Template - verify upload template API request is handled without mandatory params - ostypeid")
|
|
|
|
return
|
|
|
|
def browse_upload_template_with_projectid(self,projectid):
|
|
cmd = getUploadParamsForTemplate.getUploadParamsForTemplateCmd()
|
|
cmd.zoneid = self.zone.id
|
|
cmd.format = self.test_template.format
|
|
cmd.name=self.test_template.name+self.account.name+(random.choice(string.ascii_uppercase))
|
|
cmd.account=self.account.name
|
|
cmd.domainid=self.domain.id
|
|
cmd.displaytext=self.test_template.name+self.account.name+(random.choice(string.ascii_uppercase))
|
|
cmd.hypervisor=self.test_template.hypervisor
|
|
cmd.ostypeid=self.test_template.ostypeid
|
|
cmd.projectid=projectid
|
|
#cmd.isdynamicallyscalable="false"
|
|
#cmd.type="template"
|
|
getuploadparamsresponse=self.apiclient.getUploadParamsForTemplate(cmd)
|
|
|
|
signt=getuploadparamsresponse.signature
|
|
posturl=getuploadparamsresponse.postURL
|
|
metadata=getuploadparamsresponse.metadata
|
|
expiredata=getuploadparamsresponse.expires
|
|
#url = 'http://10.147.28.7/templates/rajani-thin-volume.vhd'
|
|
url=self.test_template.url
|
|
|
|
uploadfile = url.split('/')[-1]
|
|
r = requests.get(url, stream=True)
|
|
with open(uploadfile, 'wb') as f:
|
|
for chunk in r.iter_content(chunk_size=1024):
|
|
if chunk: # filter out keep-alive new chunks
|
|
f.write(chunk)
|
|
f.flush()
|
|
|
|
files={'file':(uploadfile,open(uploadfile,'rb'),'application/octet-stream')}
|
|
|
|
headers={'x-signature':signt,'x-metadata':metadata,'x-expires':expiredata}
|
|
|
|
results = requests.post(posturl,files=files,headers=headers,verify=False)
|
|
|
|
print(results.status_code)
|
|
if results.status_code !=200:
|
|
self.fail("Upload is not fine")
|
|
|
|
self.validate_uploaded_template(self.apiclient, getuploadparamsresponse.id)
|
|
|
|
return(getuploadparamsresponse)
|
|
|
|
def browse_upload_template_multiplezones(self,lzones):
|
|
|
|
cmd = getUploadParamsForTemplate.getUploadParamsForTemplateCmd()
|
|
cmd.zoneid ="-1"
|
|
cmd.format = self.test_template.format
|
|
cmd.name=self.test_template.name+self.account.name+(random.choice(string.ascii_uppercase))
|
|
cmd.account=self.account.name
|
|
cmd.domainid=self.domain.id
|
|
cmd.displaytext=self.test_template.name+self.account.name+(random.choice(string.ascii_uppercase))
|
|
cmd.hypervisor=self.test_template.hypervisor
|
|
cmd.ostypeid=self.test_template.ostypeid
|
|
#cmd.isdynamicallyscalable="false"
|
|
#cmd.type="template"
|
|
getuploadparamsresponse=self.apiclient.getUploadParamsForTemplate(cmd)
|
|
|
|
signt=getuploadparamsresponse.signature
|
|
posturl=getuploadparamsresponse.postURL
|
|
metadata=getuploadparamsresponse.metadata
|
|
expiredata=getuploadparamsresponse.expires
|
|
#url = 'http://10.147.28.7/templates/rajani-thin-volume.vhd'
|
|
url=self.test_template.url
|
|
|
|
uploadfile = url.split('/')[-1]
|
|
r = requests.get(url, stream=True)
|
|
with open(uploadfile, 'wb') as f:
|
|
for chunk in r.iter_content(chunk_size=1024):
|
|
if chunk: # filter out keep-alive new chunks
|
|
f.write(chunk)
|
|
f.flush()
|
|
|
|
#uploadfile='rajani-thin-volume.vhd'
|
|
|
|
#files={'file':('rajani-thin-volume.vhd',open(uploadfile,'rb'),'application/octet-stream')}
|
|
|
|
#headers={'x-signature':signt,'x-metadata':metadata,'x-expires':expiredata}
|
|
|
|
files={'file':(uploadfile,open(uploadfile,'rb'),'application/octet-stream')}
|
|
|
|
headers={'x-signature':signt,'x-metadata':metadata,'x-expires':expiredata}
|
|
|
|
results = requests.post(posturl,files=files,headers=headers,verify=False)
|
|
|
|
print(results.status_code)
|
|
if results.status_code !=200:
|
|
self.fail("Upload is not fine")
|
|
|
|
for z1 in lzones:
|
|
self.validate_uploaded_template(self.apiclient, getuploadparamsresponse.id)
|
|
|
|
return(getuploadparamsresponse)
|
|
|
|
def uploadtemplate(self):
|
|
cmd = getUploadParamsForTemplate.getUploadParamsForTemplateCmd()
|
|
cmd.zoneid = self.zone.id
|
|
cmd.format = self.test_template.format
|
|
cmd.name=self.test_template.name+self.account.name+(random.choice(string.ascii_uppercase))
|
|
cmd.account=self.account.name
|
|
cmd.domainid=self.domain.id
|
|
cmd.displaytext=self.test_template.name+self.account.name+(random.choice(string.ascii_uppercase))
|
|
cmd.hypervisor=self.test_template.hypervisor
|
|
cmd.ostypeid=self.test_template.ostypeid
|
|
#cmd.type="template"
|
|
getuploadparamsresponse=self.apiclient.getUploadParamsForTemplate(cmd)
|
|
|
|
signt=getuploadparamsresponse.signature
|
|
posturl=getuploadparamsresponse.postURL
|
|
metadata=getuploadparamsresponse.metadata
|
|
expiredata=getuploadparamsresponse.expires
|
|
#url = 'http://10.147.28.7/templates/rajani-thin-volume.vhd'
|
|
url=self.test_template.url
|
|
|
|
uploadfile = url.split('/')[-1]
|
|
r = requests.get(url, stream=True)
|
|
with open(uploadfile, 'wb') as f:
|
|
for chunk in r.iter_content(chunk_size=1024):
|
|
if chunk: # filter out keep-alive new chunks
|
|
f.write(chunk)
|
|
f.flush()
|
|
|
|
#uploadfile='rajani-thin-volume.vhd'
|
|
|
|
#files={'file':('rajani-thin-volume.vhd',open(uploadfile,'rb'),'application/octet-stream')}
|
|
|
|
#headers={'x-signature':signt,'x-metadata':metadata,'x-expires':expiredata}
|
|
|
|
files={'file':(uploadfile,open(uploadfile,'rb'),'application/octet-stream')}
|
|
|
|
headers={'x-signature':signt,'x-metadata':metadata,'x-expires':expiredata}
|
|
|
|
results = requests.post(posturl,files=files,headers=headers,verify=False)
|
|
time.sleep(60)
|
|
|
|
print(results.status_code)
|
|
if results.status_code !=200:
|
|
self.fail("Upload is not fine")
|
|
|
|
return(getuploadparamsresponse)
|
|
|
|
def multiple_browse_upload_template(self):
|
|
|
|
templ1=self.uploadtemplate()
|
|
templ2=self.uploadtemplate()
|
|
templ3=self.uploadtemplate()
|
|
|
|
self.validate_uploaded_template(self.apiclient, templ1.id)
|
|
self.validate_uploaded_template(self.apiclient, templ2.id)
|
|
self.validate_uploaded_template(self.apiclient, templ3.id)
|
|
|
|
self.delete_template(templ1)
|
|
self.delete_template(templ2)
|
|
self.delete_template(templ3)
|
|
return
|
|
|
|
def validate_vm(self, apiclient, vm_id, state, retries=72, interval=5):
|
|
|
|
"""Check if vm will be running in 6 minute"""
|
|
while retries > -1:
|
|
time.sleep(interval)
|
|
vm_response = list_virtual_machines(
|
|
apiclient,
|
|
id=vm_id
|
|
)
|
|
|
|
if isinstance(vm_response, list):
|
|
vm = vm_response[0]
|
|
if not hasattr(vm, 'state'):
|
|
retries = retries - 1
|
|
continue
|
|
|
|
# If vm is Running for x number of retries
|
|
if vm.state == state:
|
|
return
|
|
|
|
else:
|
|
retries = retries - 1
|
|
continue
|
|
|
|
else:
|
|
retries = retries - 1
|
|
raise Exception("VM failed exception.")
|
|
|
|
def deploy_vm(self,template):
|
|
virtual_machine = VirtualMachine.create(
|
|
self.apiclient,
|
|
self.testdata["virtual_machine"],
|
|
templateid=template.id,
|
|
zoneid=self.zone.id,
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
serviceofferingid=self.service_offering.id,
|
|
)
|
|
self.validate_vm(self.apiclient, vm_id = virtual_machine.id, state="Running")
|
|
return(virtual_machine)
|
|
|
|
def attach_volume(self,vmlist,volid):
|
|
|
|
list_volume_response = Volume.list(
|
|
self.apiclient,
|
|
id=volid
|
|
)
|
|
print(list_volume_response[0])
|
|
vmlist.attach_volume(
|
|
self.apiclient,
|
|
list_volume_response[0]
|
|
)
|
|
list_volume_response = Volume.list(
|
|
self.apiclient,
|
|
virtualmachineid=vmlist.id,
|
|
type='DATADISK',
|
|
listall=True
|
|
)
|
|
self.assertNotEqual(
|
|
list_volume_response,
|
|
None,
|
|
"Check if volume exists in ListVolumes")
|
|
self.assertEqual(
|
|
isinstance(list_volume_response, list),
|
|
True,
|
|
"Check list volumes response for valid list")
|
|
self.validate_uploaded_volume(volid,'Ready')
|
|
|
|
def validate_uploaded_volume(self, volid, status):
|
|
list_volume_response = Volume.list(
|
|
self.apiclient,
|
|
id=volid,
|
|
listall=True
|
|
)
|
|
|
|
self.assertNotEqual(
|
|
list_volume_response,
|
|
None,
|
|
"Check if volume exists in ListTemplates"
|
|
)
|
|
|
|
self.assertEqual(
|
|
list_volume_response[0].status,
|
|
status,
|
|
"Check volume status in List Volumes"
|
|
)
|
|
return
|
|
|
|
def reboot_vm(self,vmdetails):
|
|
vmdetails.reboot(self.apiclient)
|
|
self.validate_vm(self.apiclient, vm_id=vmdetails.id, state="Running")
|
|
|
|
def stop_vm(self,vmdetails):
|
|
vmdetails.stop(self.apiclient)
|
|
self.validate_vm(self.apiclient, vm_id=vmdetails.id, state="Stopped")
|
|
|
|
def start_vm(self,vmdetails):
|
|
vmdetails.start(self.apiclient)
|
|
self.validate_vm(self.apiclient, vm_id=vmdetails.id, state="Running")
|
|
|
|
def vmoperations(self,vmdetails):
|
|
self.reboot_vm(vmdetails)
|
|
|
|
self.stop_vm(vmdetails)
|
|
|
|
self.start_vm(vmdetails)
|
|
|
|
def detach_volume(self,vmdetails,volid):
|
|
"""Detach a Volume attached to a VM
|
|
"""
|
|
list_volume_response = Volume.list(
|
|
self.apiclient,
|
|
id=volid
|
|
)
|
|
print(list_volume_response[0])
|
|
vmdetails.detach_volume(self.apiclient,list_volume_response[0])
|
|
|
|
# Sleep to ensure the current state will reflected in other calls
|
|
time.sleep(self.testdata["sleep"])
|
|
|
|
list_volume_response = Volume.list(
|
|
self.apiclient,
|
|
id=volid
|
|
)
|
|
self.assertNotEqual(
|
|
list_volume_response,
|
|
None,
|
|
"Check if volume exists in ListVolumes"
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_volume_response, list),
|
|
True,
|
|
"Check list volumes response for valid list"
|
|
)
|
|
volume = list_volume_response[0]
|
|
self.assertEqual(
|
|
volume.virtualmachineid,
|
|
None,
|
|
"Check if volume state (detached) is reflected"
|
|
)
|
|
|
|
self.assertEqual(
|
|
volume.vmname,
|
|
None,
|
|
"Check if volume state (detached) is reflected"
|
|
)
|
|
return
|
|
|
|
def restore_vm(self,vmdetails):
|
|
"""Test recover Virtual Machine
|
|
"""
|
|
cmd = restoreVirtualMachine.restoreVirtualMachineCmd()
|
|
cmd.virtualmachineid = vmdetails.id
|
|
self.apiclient.recoverVirtualMachine(cmd)
|
|
|
|
list_vm_response = list_virtual_machines(
|
|
self.apiclient,
|
|
id=vmdetails.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_vm_response, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
|
|
self.assertNotEqual(
|
|
len(list_vm_response),
|
|
0,
|
|
"Check VM available in List Virtual Machines"
|
|
)
|
|
|
|
self.assertEqual(
|
|
list_vm_response[0].state,
|
|
"Running",
|
|
"Check virtual machine is in Running state"
|
|
)
|
|
|
|
return
|
|
|
|
def restore_vm_fail(self,vmdetails):
|
|
|
|
cmd = restoreVirtualMachine.restoreVirtualMachineCmd()
|
|
cmd.virtualmachineid = vmdetails.id
|
|
success= False
|
|
try:
|
|
self.apiclient.recoverVirtualMachine(cmd)
|
|
except Exception as ex:
|
|
if "isn't available in the zone" in str(ex):
|
|
success = True
|
|
self.assertEqual(
|
|
success,
|
|
True,
|
|
"Restore VM with Deleted Template - Verify Restore VM is handled when template with which VM created id deleted")
|
|
|
|
return
|
|
|
|
def deletevolume(self,volumeid):
|
|
"""Delete a Volume attached to a VM
|
|
"""
|
|
|
|
cmd = deleteVolume.deleteVolumeCmd()
|
|
cmd.id = volumeid
|
|
|
|
self.apiclient.deleteVolume(cmd)
|
|
|
|
list_volume_response = Volume.list(
|
|
self.apiclient,
|
|
id=volumeid,
|
|
type='DATADISK'
|
|
)
|
|
self.assertEqual(
|
|
list_volume_response,
|
|
None,
|
|
"Check if volume exists in ListVolumes"
|
|
)
|
|
return
|
|
|
|
def destroy_vm(self,vmdetails):
|
|
|
|
vmdetails.delete(self.apiclient, expunge=False)
|
|
|
|
list_vm_response = list_virtual_machines(
|
|
self.apiclient,
|
|
id=vmdetails.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_vm_response, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
|
|
self.assertNotEqual(
|
|
len(list_vm_response),
|
|
0,
|
|
"Check VM available in List Virtual Machines"
|
|
)
|
|
|
|
self.assertEqual(
|
|
list_vm_response[0].state,
|
|
"Destroyed",
|
|
"Check virtual machine is in destroyed state"
|
|
)
|
|
return
|
|
|
|
def recover_destroyed_vm(self,vmdetails):
|
|
|
|
cmd = recoverVirtualMachine.recoverVirtualMachineCmd()
|
|
cmd.id = vmdetails.id
|
|
self.apiclient.recoverVirtualMachine(cmd)
|
|
|
|
list_vm_response = list_virtual_machines(
|
|
self.apiclient,
|
|
id=vmdetails.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_vm_response, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
|
|
self.assertNotEqual(
|
|
len(list_vm_response),
|
|
0,
|
|
"Check VM available in List Virtual Machines"
|
|
)
|
|
|
|
self.assertEqual(
|
|
list_vm_response[0].state,
|
|
"Stopped",
|
|
"Check virtual machine is in Stopped state"
|
|
)
|
|
|
|
return
|
|
|
|
def expunge_vm(self,vmdetails):
|
|
|
|
self.debug("Expunge VM-ID: %s" % vmdetails.id)
|
|
|
|
cmd = destroyVirtualMachine.destroyVirtualMachineCmd()
|
|
cmd.id = vmdetails.id
|
|
self.apiclient.destroyVirtualMachine(cmd)
|
|
|
|
config = Configurations.list(
|
|
self.apiclient,
|
|
name='expunge.delay'
|
|
)
|
|
|
|
expunge_delay = int(config[0].value)
|
|
time.sleep(expunge_delay * 2)
|
|
|
|
#VM should be destroyed unless expunge thread hasn't run
|
|
#Wait for two cycles of the expunge thread
|
|
config = Configurations.list(
|
|
self.apiclient,
|
|
name='expunge.interval'
|
|
)
|
|
expunge_cycle = int(config[0].value)
|
|
wait_time = expunge_cycle * 4
|
|
while wait_time >= 0:
|
|
list_vm_response = list_virtual_machines(
|
|
self.apiclient,
|
|
id=vmdetails.id
|
|
)
|
|
if not list_vm_response:
|
|
break
|
|
self.debug("Waiting for VM to expunge")
|
|
time.sleep(expunge_cycle)
|
|
wait_time = wait_time - expunge_cycle
|
|
|
|
self.debug("listVirtualMachines response: %s" % list_vm_response)
|
|
|
|
self.assertEqual(list_vm_response,None,"Check Expunged virtual machine is in listVirtualMachines response")
|
|
return
|
|
|
|
list_vm_response = list_virtual_machines(
|
|
self.apiclient,
|
|
id=vmdetails.id
|
|
)
|
|
if isinstance(list_vm_response, list):
|
|
self.fail("VM has not been expunged")
|
|
|
|
def waitForSystemVMAgent(self, vmname):
|
|
timeout = self.testdata["timeout"]
|
|
|
|
while True:
|
|
list_host_response = list_hosts(
|
|
self.apiclient,
|
|
name=vmname
|
|
)
|
|
|
|
if list_host_response and list_host_response[0].state == 'Up':
|
|
break
|
|
|
|
if timeout == 0:
|
|
raise Exception("Timed out waiting for SSVM agent to be Up")
|
|
|
|
time.sleep(self.testdata["sleep"])
|
|
timeout = timeout - 1
|
|
|
|
def ssvm_internals(self):
|
|
|
|
list_ssvm_response = list_ssvms(
|
|
self.apiclient,
|
|
systemvmtype='secondarystoragevm',
|
|
state='Running',
|
|
zoneid=self.zone.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_ssvm_response, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
ssvm = list_ssvm_response[0]
|
|
|
|
hosts = list_hosts(
|
|
self.apiclient,
|
|
id=ssvm.hostid
|
|
)
|
|
self.assertEqual(
|
|
isinstance(hosts, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
host = hosts[0]
|
|
|
|
self.debug("Running SSVM check script")
|
|
|
|
if self.hypervisor.lower() in ('vmware', 'hyperv'):
|
|
#SSH into SSVMs is done via management server for Vmware and Hyper-V
|
|
result = get_process_status(
|
|
self.apiclient.connection.mgtSvr,
|
|
22,
|
|
self.apiclient.connection.user,
|
|
self.apiclient.connection.passwd,
|
|
ssvm.privateip,
|
|
"/usr/local/cloud/systemvm/ssvm-check.sh |grep -e ERROR -e WARNING -e FAIL",
|
|
hypervisor=self.hypervisor
|
|
)
|
|
else:
|
|
try:
|
|
host.user, host.passwd = get_host_credentials(self.config, host.ipaddress)
|
|
result = get_process_status(
|
|
host.ipaddress,
|
|
22,
|
|
host.user,
|
|
host.passwd,
|
|
ssvm.linklocalip,
|
|
"/usr/local/cloud/systemvm/ssvm-check.sh |grep -e ERROR -e WARNING -e FAIL"
|
|
)
|
|
except KeyError:
|
|
self.skipTest("Marvin configuration has no host credentials to check router services")
|
|
res = str(result)
|
|
self.debug("SSVM script output: %s" % res)
|
|
|
|
self.assertEqual(
|
|
res.count("ERROR"),
|
|
1,
|
|
"Check for Errors in tests"
|
|
)
|
|
|
|
self.assertEqual(
|
|
res.count("WARNING"),
|
|
1,
|
|
"Check for warnings in tests"
|
|
)
|
|
|
|
#Check status of cloud service
|
|
if self.hypervisor.lower() in ('vmware', 'hyperv'):
|
|
#SSH into SSVMs is done via management server for Vmware and Hyper-V
|
|
result = get_process_status(
|
|
self.apiclient.connection.mgtSvr,
|
|
22,
|
|
self.apiclient.connection.user,
|
|
self.apiclient.connection.passwd,
|
|
ssvm.privateip,
|
|
"systemctl is-active cloud",
|
|
hypervisor=self.hypervisor
|
|
)
|
|
else:
|
|
try:
|
|
host.user, host.passwd = get_host_credentials(self.config, host.ipaddress)
|
|
result = get_process_status(
|
|
host.ipaddress,
|
|
22,
|
|
host.user,
|
|
host.passwd,
|
|
ssvm.linklocalip,
|
|
"systemctl is-active cloud"
|
|
)
|
|
except KeyError:
|
|
self.skipTest("Marvin configuration has no host credentials to check router services")
|
|
res = str(result)
|
|
self.debug("Cloud Process status: %s" % res)
|
|
# Apache CloudStack service (type=secstorage) is running: process id: 2346
|
|
self.assertEqual(
|
|
res.count("active"),
|
|
1,
|
|
"Check cloud service is running or not"
|
|
)
|
|
return
|
|
|
|
def list_sec_storage_vm(self):
|
|
|
|
list_ssvm_response = list_ssvms(
|
|
self.apiclient,
|
|
systemvmtype='secondarystoragevm',
|
|
state='Running',
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_ssvm_response, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
#Verify SSVM response
|
|
self.assertNotEqual(
|
|
len(list_ssvm_response),
|
|
0,
|
|
"Check list System VMs response"
|
|
)
|
|
|
|
list_zones_response = list_zones(self.apiclient)
|
|
|
|
self.assertEqual(
|
|
isinstance(list_zones_response, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
|
|
self.debug("Number of zones: %s" % len(list_zones_response))
|
|
self.debug("Number of SSVMs: %s" % len(list_ssvm_response))
|
|
# Number of Sec storage VMs = No of Zones
|
|
self.assertEqual(
|
|
len(list_ssvm_response),
|
|
len(list_zones_response),
|
|
"Check number of SSVMs with number of zones"
|
|
)
|
|
#For each secondary storage VM check private IP,
|
|
#public IP, Control IP and DNS
|
|
for ssvm in list_ssvm_response:
|
|
|
|
self.debug("SSVM state: %s" % ssvm.state)
|
|
self.assertEqual(
|
|
ssvm.state,
|
|
'Running',
|
|
"Check whether state of SSVM is running"
|
|
)
|
|
|
|
self.assertEqual(
|
|
hasattr(ssvm, 'privateip'),
|
|
True,
|
|
"Check whether SSVM has private IP field"
|
|
)
|
|
|
|
self.assertEqual(
|
|
hasattr(ssvm, 'linklocalip'),
|
|
True,
|
|
"Check whether SSVM has Control IP field"
|
|
)
|
|
|
|
self.assertEqual(
|
|
hasattr(ssvm, 'publicip'),
|
|
True,
|
|
"Check whether SSVM has public IP field"
|
|
)
|
|
|
|
#Fetch corresponding ip ranges information from listVlanIpRanges
|
|
ipranges_response = list_vlan_ipranges(
|
|
self.apiclient,
|
|
zoneid=ssvm.zoneid
|
|
)
|
|
self.assertEqual(
|
|
isinstance(ipranges_response, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
iprange = ipranges_response[0]
|
|
|
|
#Fetch corresponding Physical Network of SSVM's Zone
|
|
listphyntwk = PhysicalNetwork.list(
|
|
self.apiclient,
|
|
zoneid=ssvm.zoneid
|
|
)
|
|
|
|
# Execute the following assertion in all zones except EIP-ELB Zones
|
|
if not (self.zone.networktype.lower() == 'basic' and isinstance(NetScaler.list(self.apiclient,physicalnetworkid=listphyntwk[0].id), list) is True):
|
|
self.assertEqual(
|
|
ssvm.gateway,
|
|
iprange.gateway,
|
|
"Check gateway with that of corresponding ip range"
|
|
)
|
|
|
|
#Fetch corresponding zone information from listZones
|
|
zone_response = list_zones(
|
|
self.apiclient,
|
|
id=ssvm.zoneid
|
|
)
|
|
self.assertEqual(
|
|
isinstance(zone_response, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertEqual(
|
|
ssvm.dns1,
|
|
zone_response[0].dns1,
|
|
"Check DNS1 with that of corresponding zone"
|
|
)
|
|
|
|
self.assertEqual(
|
|
ssvm.dns2,
|
|
zone_response[0].dns2,
|
|
"Check DNS2 with that of corresponding zone"
|
|
)
|
|
return
|
|
|
|
def stop_ssvm(self):
|
|
|
|
list_ssvm_response = list_ssvms(
|
|
self.apiclient,
|
|
systemvmtype='secondarystoragevm',
|
|
state='Running',
|
|
zoneid=self.zone.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_ssvm_response, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
ssvm = list_ssvm_response[0]
|
|
|
|
hosts = list_hosts(
|
|
self.apiclient,
|
|
id=ssvm.hostid
|
|
)
|
|
self.assertEqual(
|
|
isinstance(hosts, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
host = hosts[0]
|
|
|
|
self.debug("Stopping SSVM: %s" % ssvm.id)
|
|
cmd = stopSystemVm.stopSystemVmCmd()
|
|
cmd.id = ssvm.id
|
|
self.apiclient.stopSystemVm(cmd)
|
|
|
|
timeout = self.testdata["timeout"]
|
|
while True:
|
|
list_ssvm_response = list_ssvms(
|
|
self.apiclient,
|
|
id=ssvm.id
|
|
)
|
|
if isinstance(list_ssvm_response, list):
|
|
if list_ssvm_response[0].state == 'Running':
|
|
break
|
|
if timeout == 0:
|
|
raise Exception("List SSVM call failed!")
|
|
|
|
time.sleep(self.testdata["sleep"])
|
|
timeout = timeout - 1
|
|
|
|
self.assertEqual(
|
|
isinstance(list_ssvm_response, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
ssvm_response = list_ssvm_response[0]
|
|
self.debug("SSVM state after debug: %s" % ssvm_response.state)
|
|
self.assertEqual(
|
|
ssvm_response.state,
|
|
'Running',
|
|
"Check whether SSVM is running or not"
|
|
)
|
|
# Wait for the agent to be up
|
|
self.waitForSystemVMAgent(ssvm_response.name)
|
|
|
|
# Call above tests to ensure SSVM is properly running
|
|
self.list_sec_storage_vm()
|
|
|
|
def reboot_ssvm(self):
|
|
|
|
list_ssvm_response = list_ssvms(
|
|
self.apiclient,
|
|
systemvmtype='secondarystoragevm',
|
|
state='Running',
|
|
zoneid=self.zone.id
|
|
)
|
|
|
|
self.assertEqual(
|
|
isinstance(list_ssvm_response, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
|
|
ssvm_response = list_ssvm_response[0]
|
|
|
|
hosts = list_hosts(
|
|
self.apiclient,
|
|
id=ssvm_response.hostid
|
|
)
|
|
self.assertEqual(
|
|
isinstance(hosts, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
host = hosts[0]
|
|
|
|
#Store the public & private IP values before reboot
|
|
old_public_ip = ssvm_response.publicip
|
|
old_private_ip = ssvm_response.privateip
|
|
|
|
self.debug("Rebooting SSVM: %s" % ssvm_response.id)
|
|
cmd = rebootSystemVm.rebootSystemVmCmd()
|
|
cmd.id = ssvm_response.id
|
|
self.apiclient.rebootSystemVm(cmd)
|
|
|
|
timeout = self.testdata["timeout"]
|
|
while True:
|
|
list_ssvm_response = list_ssvms(
|
|
self.apiclient,
|
|
id=ssvm_response.id
|
|
)
|
|
if isinstance(list_ssvm_response, list):
|
|
if list_ssvm_response[0].state == 'Running':
|
|
break
|
|
if timeout == 0:
|
|
raise Exception("List SSVM call failed!")
|
|
|
|
time.sleep(self.testdata["sleep"])
|
|
timeout = timeout - 1
|
|
|
|
ssvm_response = list_ssvm_response[0]
|
|
self.debug("SSVM State: %s" % ssvm_response.state)
|
|
self.assertEqual(
|
|
'Running',
|
|
str(ssvm_response.state),
|
|
"Check whether CPVM is running or not"
|
|
)
|
|
|
|
self.assertEqual(
|
|
ssvm_response.publicip,
|
|
old_public_ip,
|
|
"Check Public IP after reboot with that of before reboot"
|
|
)
|
|
|
|
self.assertEqual(
|
|
ssvm_response.privateip,
|
|
old_private_ip,
|
|
"Check Private IP after reboot with that of before reboot"
|
|
)
|
|
|
|
# Wait for the agent to be up
|
|
self.waitForSystemVMAgent(ssvm_response.name)
|
|
|
|
return
|
|
|
|
def destroy_ssvm(self):
|
|
|
|
list_ssvm_response = list_ssvms(
|
|
self.apiclient,
|
|
systemvmtype='secondarystoragevm',
|
|
state='Running',
|
|
zoneid=self.zone.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_ssvm_response, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
ssvm_response = list_ssvm_response[0]
|
|
|
|
old_name = ssvm_response.name
|
|
|
|
self.debug("Destroying SSVM: %s" % ssvm_response.id)
|
|
cmd = destroySystemVm.destroySystemVmCmd()
|
|
cmd.id = ssvm_response.id
|
|
self.apiclient.destroySystemVm(cmd)
|
|
|
|
timeout = self.testdata["timeout"]
|
|
while True:
|
|
list_ssvm_response = list_ssvms(
|
|
self.apiclient,
|
|
zoneid=self.zone.id,
|
|
systemvmtype='secondarystoragevm'
|
|
)
|
|
if isinstance(list_ssvm_response, list):
|
|
if list_ssvm_response[0].state == 'Running':
|
|
break
|
|
if timeout == 0:
|
|
raise Exception("List SSVM call failed!")
|
|
|
|
time.sleep(self.testdata["sleep"])
|
|
timeout = timeout - 1
|
|
|
|
ssvm_response = list_ssvm_response[0]
|
|
|
|
# Verify Name, Public IP, Private IP and Link local IP
|
|
# for newly created SSVM
|
|
self.assertNotEqual(
|
|
ssvm_response.name,
|
|
old_name,
|
|
"Check SSVM new name with name of destroyed SSVM"
|
|
)
|
|
self.assertEqual(
|
|
hasattr(ssvm_response, 'privateip'),
|
|
True,
|
|
"Check whether SSVM has private IP field"
|
|
)
|
|
|
|
self.assertEqual(
|
|
hasattr(ssvm_response, 'linklocalip'),
|
|
True,
|
|
"Check whether SSVM has Control IP field"
|
|
)
|
|
|
|
self.assertEqual(
|
|
hasattr(ssvm_response, 'publicip'),
|
|
True,
|
|
"Check whether SSVM has public IP field"
|
|
)
|
|
|
|
# Wait for the agent to be up
|
|
self.waitForSystemVMAgent(ssvm_response.name)
|
|
|
|
return
|
|
|
|
def create_data_volume(self):
|
|
|
|
diskoffering = DiskOffering.list(self.apiclient)
|
|
self.assertTrue(
|
|
isinstance(
|
|
diskoffering,
|
|
list),
|
|
msg="DiskOffering list is not a list?")
|
|
self.assertTrue(
|
|
len(diskoffering) > 0,
|
|
"no disk offerings in the deployment")
|
|
|
|
vol = Volume.create(
|
|
self.apiclient,
|
|
services=self.testdata["volume"],
|
|
zoneid=self.zone.id,
|
|
account=self.account.name,
|
|
domainid=self.domain.id,
|
|
diskofferingid=diskoffering[0].id
|
|
)
|
|
self.assertTrue(
|
|
vol is not None, "volume creation fails in domain %s as user %s" %
|
|
(self.domain.name, self.account.name))
|
|
|
|
listed_vol = Volume.list(self.apiclient, id=vol.id)
|
|
self.assertTrue(
|
|
listed_vol is not None and isinstance(
|
|
listed_vol,
|
|
list),
|
|
"invalid response from listVolumes for volume %s" %
|
|
vol.id)
|
|
self.assertTrue(
|
|
listed_vol[0].id == vol.id,
|
|
"Volume returned by list volumes %s not matching with queried\
|
|
volume %s in domain %s" %
|
|
(listed_vol[0].id,
|
|
vol.id,
|
|
self.account.name))
|
|
return(listed_vol[0])
|
|
|
|
def attach_data_volume(self,volume,vmdetails):
|
|
|
|
list_volume_response = Volume.list(
|
|
self.apiclient,
|
|
id=volume.id
|
|
)
|
|
self.assertNotEqual(
|
|
list_volume_response,
|
|
None,
|
|
"Check if volume exists in ListVolumes"
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_volume_response, list),
|
|
True,
|
|
"Check list volumes response for valid list"
|
|
)
|
|
volume = list_volume_response[0]
|
|
|
|
self.assertEqual(
|
|
volume.type,
|
|
'DATADISK',
|
|
"Check volume type from list volume response"
|
|
)
|
|
|
|
self.assertEqual(
|
|
hasattr(volume, 'vmname'),
|
|
True,
|
|
"Check whether volume has vmname field"
|
|
)
|
|
self.assertEqual(
|
|
hasattr(volume, 'virtualmachineid'),
|
|
True,
|
|
"Check whether volume has virtualmachineid field"
|
|
)
|
|
|
|
# Attach volume to VM
|
|
self.debug("Attach volume: %s to VM: %s" % (
|
|
volume.id,
|
|
vmdetails.id
|
|
))
|
|
vmdetails.attach_volume(self.apiclient, volume)
|
|
|
|
# Check all volumes attached to same VM
|
|
list_volume_response = Volume.list(
|
|
self.apiclient,
|
|
virtualmachineid=vmdetails.id,
|
|
type='DATADISK',
|
|
listall=True
|
|
)
|
|
self.assertNotEqual(
|
|
list_volume_response,
|
|
None,
|
|
"Check if volume exists in ListVolumes"
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_volume_response, list),
|
|
True,
|
|
"Check list volumes response for valid list"
|
|
)
|
|
volume = list_volume_response[0]
|
|
self.assertEqual(
|
|
volume.vmname,
|
|
vmdetails.name,
|
|
"Check virtual machine name in list volumes response"
|
|
)
|
|
self.assertEqual(
|
|
volume.virtualmachineid,
|
|
vmdetails.id,
|
|
"Check VM ID in list Volume response"
|
|
)
|
|
return
|
|
|
|
def delete_template(self,templatedetails):
|
|
|
|
list_template_response = Template.list(
|
|
self.apiclient,
|
|
templatefilter="all",
|
|
id=templatedetails.id,
|
|
zoneid=self.zone.id)
|
|
|
|
if list_template_response is None:
|
|
self.debug("Template is not available")
|
|
return
|
|
|
|
cmd = deleteTemplate.deleteTemplateCmd()
|
|
cmd.id = templatedetails.id
|
|
self.apiclient.deleteTemplate(cmd)
|
|
|
|
list_template_response = Template.list(
|
|
self.apiclient,
|
|
templatefilter="all",
|
|
id=templatedetails.id,
|
|
zoneid=self.zone.id
|
|
)
|
|
self.assertEqual(
|
|
list_template_response,
|
|
None,
|
|
"Check template available in List Templates"
|
|
)
|
|
return
|
|
|
|
def detach_data_volume(self,volume,vmdetails):
|
|
|
|
self.debug("Detach volume: %s to VM: %s" % (
|
|
volume.id,
|
|
vmdetails.id
|
|
))
|
|
vmdetails.detach_volume(self.apiclient, volume)
|
|
|
|
# Sleep to ensure the current state will reflected in other calls
|
|
time.sleep(self.testdata["sleep"])
|
|
|
|
list_volume_response = Volume.list(
|
|
self.apiclient,
|
|
id=volume.id
|
|
)
|
|
self.assertNotEqual(
|
|
list_volume_response,
|
|
None,
|
|
"Check if volume exists in ListVolumes"
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_volume_response, list),
|
|
True,
|
|
"Check list volumes response for valid list"
|
|
)
|
|
volumelist = list_volume_response[0]
|
|
self.assertEqual(
|
|
volumelist.virtualmachineid,
|
|
None,
|
|
"Check if volume state (detached) is reflected"
|
|
)
|
|
|
|
self.assertEqual(
|
|
volumelist.vmname,
|
|
None,
|
|
"Check if volume state (detached) is reflected"
|
|
)
|
|
return
|
|
|
|
# was tags = ["advanced", "advancedns", "smoke", "basic"]
|
|
@attr(tags = ["TODO"], required_hardware="true")
|
|
def test_01_Browser_template_Life_cycle_tpath(self):
|
|
"""
|
|
Test Browser_template_Life_cycle
|
|
"""
|
|
#try:
|
|
|
|
self.debug("========================= Test 1: Upload Browser based template and validate ========================= ")
|
|
browseup_template=self.browse_upload_template()
|
|
|
|
self.debug("========================= Test 2: Deploy a VM with uploaded template and validate VM Operations========================= ")
|
|
|
|
vm1details=self.deploy_vm(browseup_template)
|
|
|
|
self.vmoperations(vm1details)
|
|
|
|
self.debug("========================= Test 3: Attach DATA DISK to the VM ")
|
|
|
|
cvolume=self.create_data_volume()
|
|
self.attach_data_volume(cvolume, vm1details)
|
|
self.vmoperations(vm1details)
|
|
|
|
self.debug("========================= Test 4: Restore VM created with Uploaded template========================= ")
|
|
|
|
self.restore_vm(vm1details)
|
|
|
|
self.debug("========================= Test 5: Detach DATA DISK to the VM ")
|
|
|
|
self.detach_data_volume(cvolume,vm1details)
|
|
self.vmoperations(vm1details)
|
|
|
|
self.deletevolume(cvolume.id)
|
|
|
|
|
|
self.debug("========================= Test 6: Expunge VM created with Uploaded template========================= ")
|
|
|
|
self.expunge_vm(vm1details)
|
|
|
|
self.debug("========================= Test 7: Destroy VM ========================= ")
|
|
|
|
vm2details=self.deploy_vm(self.template)
|
|
|
|
vm2details=self.deploy_vm(browseup_template)
|
|
self.destroy_vm(vm2details)
|
|
|
|
self.debug("========================= Test 8: Recover destroyed VM which has Uploaded volumes attached========================= ")
|
|
|
|
self.recover_destroyed_vm(vm2details)
|
|
self.expunge_vm(vm2details)
|
|
|
|
self.debug("========================= Test 9: Delete the Uploaded Template========================= ")
|
|
self.debug(browseup_template)
|
|
self.delete_template(browseup_template)
|
|
|
|
self.debug("========================= Test 10: Upload Multiple templates========================= ")
|
|
|
|
self.multiple_browse_upload_template()
|
|
|
|
# except Exception as e:
|
|
# self.fail("Exception occurred : %s" % e)
|
|
return
|
|
|
|
# was tags = ["advanced", "advancedns", "smoke", "basic"]
|
|
@attr(tags = ["TODO"], required_hardware="true")
|
|
def test_02_SSVM_Life_Cycle_With_Browser_Template_TPath(self):
|
|
"""
|
|
Test SSVM_Life_Cycle_With_Browser_template_TPath
|
|
"""
|
|
try:
|
|
|
|
self.debug("========================= Test 11: Stop and Start SSVM and Perform Browser based volume validations ========================= ")
|
|
|
|
self.stop_ssvm()
|
|
ssvm1browseup_template=self.browse_upload_template()
|
|
|
|
ssvm1vm1details=self.deploy_vm(ssvm1browseup_template)
|
|
#ssvm1vm1details=self.deploy_vm(self.template)
|
|
|
|
self.vmoperations(ssvm1vm1details)
|
|
|
|
self.expunge_vm(ssvm1vm1details)
|
|
|
|
self.debug("========================= Test 12: Reboot SSVM and Perform Browser based volume validations ========================= ")
|
|
|
|
self.reboot_ssvm()
|
|
ssvm2browseup_template=self.browse_upload_template()
|
|
|
|
ssvm2vm1details=self.deploy_vm(ssvm2browseup_template)
|
|
|
|
#ssvm2vm1details=self.deploy_vm(self.template)
|
|
self.vmoperations(ssvm2vm1details)
|
|
|
|
self.expunge_vm(ssvm2vm1details)
|
|
|
|
self.debug("========================= Test 13: Destroy SSVM and Perform Browser based volume validations ========================= ")
|
|
|
|
self.destroy_ssvm()
|
|
ssvm3browseup_template=self.browse_upload_template()
|
|
|
|
ssvm3vm1details=self.deploy_vm(ssvm3browseup_template)
|
|
|
|
#ssvm2vm1details=self.deploy_vm(self.template)
|
|
self.vmoperations(ssvm3vm1details)
|
|
|
|
self.expunge_vm(ssvm3vm1details)
|
|
|
|
except Exception as e:
|
|
self.fail("Exception occurred : %s" % e)
|
|
return
|
|
|
|
@attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="true")
|
|
def test_03_Browser_template_upload_multiple_zones(self):
|
|
"""
|
|
Test Browser_template_upload_multiple_zones
|
|
"""
|
|
|
|
cmd = listZones.listZonesCmd()
|
|
zonelist=self.apiclient.listZones(cmd)
|
|
if len(zonelist) <2:
|
|
raise self.skipTest("Only one zone available hence skipping")
|
|
try:
|
|
|
|
self.debug("========================= Test 14: Upload Browser based template into multiple zones ========================= ")
|
|
browseup_template=self.browse_upload_template_multiplezones(zonelist)
|
|
|
|
except Exception as e:
|
|
self.fail("Exception occurred : %s" % e)
|
|
return
|
|
|
|
# was tags = ["advanced", "advancedns", "smoke", "basic"]
|
|
@attr(tags = ["TODO"], required_hardware="true")
|
|
def test_04_Browser_template_ResetVM_With_Deleted_Template(self):
|
|
"""
|
|
Test Browser_template_upload_ResetVM_With_Deleted_Template
|
|
"""
|
|
try:
|
|
|
|
self.debug("========================= Test 15: Test Browser_template_upload_ResetVM_With_Deleted_Template ========================= ")
|
|
|
|
browseup_template=self.browse_upload_template()
|
|
|
|
vm1details=self.deploy_vm(browseup_template)
|
|
|
|
self.delete_template(browseup_template)
|
|
|
|
self.restore_vm_fail(vm1details)
|
|
|
|
except Exception as e:
|
|
self.fail("Exception occurred : %s" % e)
|
|
return
|
|
|
|
# was tags = ["advanced", "advancedns", "smoke", "basic"]
|
|
@attr(tags = ["TODO"], required_hardware="true")
|
|
def test_05_Browser_Upload_Template_with_all_API_parameters(self):
|
|
"""
|
|
Test Browser_Upload_Template with all API parameters
|
|
"""
|
|
try:
|
|
|
|
self.debug("========================= Test 16 & 17 Upload template with account name and domainid========================")
|
|
|
|
browseup_template1=self.browse_upload_template()
|
|
|
|
self.debug("========================= Test 18 Upload template with project id========================")
|
|
browseup_template2=self.browse_upload_template_with_projectid(self.project.id)
|
|
|
|
self.debug("========================= Test 19 Upload template with out mandatory param zone id ========================")
|
|
|
|
browseup_vol2=self.browse_upload_template_with_out_zoneid()
|
|
|
|
self.debug("========================= Test 20 Upload template with out mandatory param ostypeid ========================")
|
|
|
|
browseup_vol3=self.browse_upload_template_with_out_ostypeid()
|
|
|
|
except Exception as e:
|
|
self.fail("Exception occurred : %s" % e)
|
|
return
|
|
|
|
# was tags = ["advanced", "advancedns", "smoke", "basic"]
|
|
@attr(tags = ["TODO"], required_hardware="true")
|
|
def test_06_Browser_Upload_template_resource_limits(self):
|
|
"""
|
|
Test Browser Upload Template Resource limits
|
|
"""
|
|
try:
|
|
|
|
self.debug("========================= Test 21 Upload Template and verify Template limits========================")
|
|
initialtemplatelimit=self.gettemplatelimts()
|
|
browseup_template1=self.browse_upload_template()
|
|
# Adding time for limit to sync in background
|
|
time.sleep(120)
|
|
afteruploadtemplatelimit=self.gettemplatelimts()
|
|
|
|
if int(afteruploadtemplatelimit)!=(int(initialtemplatelimit)+1):
|
|
self.fail("Volume Resource Count is not updated")
|
|
|
|
self.delete_template(browseup_template1)
|
|
|
|
except Exception as e:
|
|
self.fail("Exception occurred : %s" % e)
|
|
return
|
|
|
|
# was tags = ["advanced", "advancedns", "smoke", "basic"]
|
|
@attr(tags = ["TODO"], required_hardware="true")
|
|
def test_07_Browser_Upload_template_secondary_storage_resource_limits(self):
|
|
"""
|
|
Test Browser_Upload_Template Secondary Storage Resource limits
|
|
"""
|
|
try:
|
|
|
|
self.debug("========================= Test 22 Upload template and verify secondary storage limits========================")
|
|
|
|
initialsecondarystoragelimit=self.getstoragelimits(11)
|
|
browseup_template1=self.browse_upload_template()
|
|
|
|
tmpldetails=Template.list(
|
|
self.apiclient,
|
|
id=browseup_template1.id,
|
|
templatefilter="all",
|
|
zoneid=self.zone.id)
|
|
|
|
|
|
afteruploadsecondarystoragelimit=self.getstoragelimits(11)
|
|
|
|
if afteruploadsecondarystoragelimit!=(initialsecondarystoragelimit+tmpldetails[0].size):
|
|
self.fail("Secondary Storage Resource Count is not updated")
|
|
|
|
self.delete_template(browseup_template1)
|
|
|
|
except Exception as e:
|
|
self.fail("Exception occurred : %s" % e)
|
|
return
|
|
|
|
# was tags = ["advanced", "advancedns", "smoke", "basic"]
|
|
@attr(tags = ["TODO"], required_hardware="true")
|
|
def test_08_Browser_Upload_template_resource_limits_after_deletion(self):
|
|
"""
|
|
Test Browser_Upload_Template Resource limits after template deletion
|
|
"""
|
|
try:
|
|
self.debug("========================= Test 23 Delete Upload template and verify template limits========================")
|
|
browseup_template1=self.browse_upload_template()
|
|
initialtemplatelimit=self.gettemplatelimts()
|
|
|
|
self.delete_template(browseup_template1)
|
|
aftertemplatelimit=self.gettemplatelimts()
|
|
|
|
if aftertemplatelimit!=(initialtemplatelimit-1):
|
|
self.fail("Template Resource Count is not updated after deletion")
|
|
|
|
except Exception as e:
|
|
self.fail("Exceptione occurred : %s" % e)
|
|
return
|
|
|
|
# was tags = ["advanced", "advancedns", "smoke", "basic"]
|
|
@attr(tags = ["TODO"], required_hardware="true")
|
|
def test_09_Browser_Upload_Volume_secondary_storage_resource_limits_after_deletion(self):
|
|
"""
|
|
Test Browser_Upload_Template Secondary Storage Resource limits after template deletion
|
|
"""
|
|
try:
|
|
self.debug("========================= Test 24 Delete Upload template and verify secondary storage limits========================")
|
|
|
|
browseup_template1=self.browse_upload_template()
|
|
|
|
tmpldetails=Template.list(
|
|
self.apiclient,
|
|
id=browseup_template1.id,
|
|
templatefilter="all",
|
|
zoneid=self.zone.id)
|
|
|
|
initialuploadprimarystoragelimit=self.getstoragelimits(11)
|
|
self.delete_template(browseup_template1)
|
|
|
|
afteruploadprimarystoragelimit=self.getstoragelimits(11)
|
|
|
|
if afteruploadprimarystoragelimit!=(initialuploadprimarystoragelimit-tmpldetails[0].size):
|
|
self.fail("Secondary Storage Resource Count is not updated after deletion")
|
|
|
|
except Exception as e:
|
|
self.fail("Exception occurred : %s" % e)
|
|
return
|
|
|
|
# @attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false")
|
|
@attr(tags = ["TODO"], required_hardware="false")
|
|
def test_browser_upload_template_incomplete(self):
|
|
"""
|
|
Test browser based incomplete template upload, followed by SSVM destroy. Template should go to UploadAbandoned state and get cleaned up.
|
|
"""
|
|
try:
|
|
self.debug("========================= Test browser based incomplete template upload ========================")
|
|
|
|
#Only register template, without uploading
|
|
cmd = getUploadParamsForTemplate.getUploadParamsForTemplateCmd()
|
|
|
|
if 'kvm' in self.hypervisor.lower():
|
|
cmd.url = 'http://dl.openvm.eu/cloudstack/centos/x86_64/centos-7-kvm.qcow2.bz2'
|
|
if 'vmware' in self.hypervisor.lower():
|
|
cmd.url = 'http://dl.openvm.eu/cloudstack/centos/x86_64/centos-7-vmware.ova'
|
|
if 'xenserver' in self.hypervisor.lower():
|
|
cmd.url = 'http://dl.openvm.eu/cloudstack/centos/x86_64/centos-7-xen.vhd.bz2'
|
|
|
|
cmd.zoneid = self.zone.id
|
|
cmd.format = self.test_template.format
|
|
cmd.name=self.test_template.name+self.account.name+(random.choice(string.ascii_uppercase))
|
|
cmd.account=self.account.name
|
|
cmd.domainid=self.domain.id
|
|
cmd.displaytext=cmd.name
|
|
cmd.hypervisor=self.test_template.hypervisor
|
|
cmd.ostypeid=self.test_template.ostypeid
|
|
template_response=self.apiclient.getUploadParamsForTemplate(cmd)
|
|
|
|
#Destroy SSVM, and wait for new one to start
|
|
self.destroy_ssvm()
|
|
|
|
#Verify that the template is cleaned up as part of sync-up during new SSVM start
|
|
list_template_response=Template.list(
|
|
self.apiclient,
|
|
id=template_response.id,
|
|
templatefilter="all",
|
|
zoneid=self.zone.id)
|
|
self.assertEqual(list_template_response, None, "Template is not cleaned up, some issue with template sync-up")
|
|
|
|
except Exception as e:
|
|
self.fail("Exceptione occurred : %s" % e)
|
|
return
|
|
|
|
@classmethod
|
|
def tearDownClass(self):
|
|
super(TestBrowseUploadVolume, self).tearDownClass()
|
|
|
|
def tearDown(self):
|
|
super(TestBrowseUploadVolume, self).tearDown()
|