mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
417 lines
15 KiB
Python
417 lines
15 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 Dedicating Public IP addresses
|
|
"""
|
|
#Import Local Modules
|
|
import marvin
|
|
from nose.plugins.attrib import attr
|
|
from marvin.cloudstackTestCase import *
|
|
from marvin.cloudstackAPI import *
|
|
from marvin.lib.utils import *
|
|
from marvin.lib.base import *
|
|
from marvin.lib.common import *
|
|
import datetime
|
|
from socket import inet_aton
|
|
from struct import unpack
|
|
|
|
class TestDedicatePublicIPRange(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.testClient = super(TestDedicatePublicIPRange, cls).getClsTestClient()
|
|
cls.apiclient = cls.testClient.getApiClient()
|
|
cls.services = cls.testClient.getParsedTestDataConfig()
|
|
# Get Zone, Domain
|
|
cls.domain = get_domain(cls.apiclient)
|
|
cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
|
|
cls.services["zoneid"] = cls.zone.id
|
|
cls.pod = get_pod(cls.apiclient, cls.zone.id)
|
|
cls._cleanup = []
|
|
# Create Account
|
|
cls.account = Account.create(
|
|
cls.apiclient,
|
|
cls.services["account"],
|
|
domainid=cls.domain.id
|
|
)
|
|
cls._cleanup.append(cls.account)
|
|
return
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
super(TestDedicatePublicIPRange,cls).tearDownClass()
|
|
|
|
def setUp(self):
|
|
self.apiclient = self.testClient.getApiClient()
|
|
self.dbclient = self.testClient.getDbConnection()
|
|
self.cleanup = []
|
|
return
|
|
|
|
def tearDown(self):
|
|
super(TestDedicatePublicIPRange,self).tearDown()
|
|
|
|
@attr(tags = ["advanced", "publiciprange", "dedicate", "release"], required_hardware="false")
|
|
def test_dedicatePublicIpRange(self):
|
|
"""Test public IP range dedication
|
|
"""
|
|
|
|
# Validate the following:
|
|
# 1. Create a Public IP range
|
|
# 2. Created IP range should be present, verify with listVlanIpRanges
|
|
# 3. Dedicate the created IP range to user account
|
|
# 4. Verify IP range is dedicated, verify with listVlanIpRanges
|
|
# 5. Release the dedicated Public IP range back to the system
|
|
# 6. Verify IP range has been released, verify with listVlanIpRanges
|
|
# 7. Delete the Public IP range
|
|
|
|
self.debug("Creating Public IP range")
|
|
self.public_ip_range = PublicIpRange.create(
|
|
self.apiclient,
|
|
self.services
|
|
)
|
|
self._cleanup.append(self.public_ip_range)
|
|
list_public_ip_range_response = PublicIpRange.list(
|
|
self.apiclient,
|
|
id=self.public_ip_range.vlan.id
|
|
)
|
|
self.debug(
|
|
"Verify listPublicIpRanges response for public ip ranges: %s" \
|
|
% self.public_ip_range.vlan.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_public_ip_range_response, list),
|
|
True,
|
|
"Check for list Public IP range response"
|
|
)
|
|
public_ip_response = list_public_ip_range_response[0]
|
|
self.assertEqual(
|
|
public_ip_response.id,
|
|
self.public_ip_range.vlan.id,
|
|
"Check public ip range response id is in listVlanIpRanges"
|
|
)
|
|
|
|
self.debug("Dedicating Public IP range");
|
|
dedicate_public_ip_range_response = PublicIpRange.dedicate(
|
|
self.apiclient,
|
|
self.public_ip_range.vlan.id,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid
|
|
)
|
|
list_public_ip_range_response = PublicIpRange.list(
|
|
self.apiclient,
|
|
id=self.public_ip_range.vlan.id
|
|
)
|
|
public_ip_response = list_public_ip_range_response[0]
|
|
self.assertEqual(
|
|
public_ip_response.account,
|
|
self.account.name,
|
|
"Check account name is in listVlanIpRanges as the account public ip range is dedicated to"
|
|
)
|
|
|
|
self.debug("Releasing Public IP range");
|
|
self.public_ip_range.release(self.apiclient)
|
|
list_public_ip_range_response = PublicIpRange.list(
|
|
self.apiclient,
|
|
id=self.public_ip_range.vlan.id
|
|
)
|
|
public_ip_response = list_public_ip_range_response[0]
|
|
self.assertIsNone(
|
|
public_ip_response.account,
|
|
"Check account name is system account in listVlanIpRanges"
|
|
)
|
|
return
|
|
|
|
@attr(tags = ["advanced", "publiciprange", "dedicate", "release"], required_hardware="false")
|
|
def test_dedicate_public_ip_range_for_system_vms(self):
|
|
"""Test public IP range dedication for SSVM and CPVM
|
|
"""
|
|
|
|
# Validate the following:
|
|
# 1. Create a Public IP range for system vms
|
|
# 2. Created IP range should be present and marked as forsystemvms=true, verify with listVlanIpRanges
|
|
# 7. Delete the Public IP range
|
|
|
|
services = {
|
|
"gateway":"192.168.99.1",
|
|
"netmask":"255.255.255.0",
|
|
"startip":"192.168.99.2",
|
|
"endip":"192.168.99.200",
|
|
"forvirtualnetwork":self.services["forvirtualnetwork"],
|
|
"zoneid":self.services["zoneid"],
|
|
"vlan":self.services["vlan"]
|
|
}
|
|
self.public_ip_range = PublicIpRange.create(
|
|
self.apiclient,
|
|
services,
|
|
forsystemvms = True
|
|
)
|
|
self.cleanup.append(self.public_ip_range)
|
|
created_ip_range_response = PublicIpRange.list(
|
|
self.apiclient,
|
|
id = self.public_ip_range.vlan.id
|
|
)
|
|
self.assertEqual(
|
|
len(created_ip_range_response),
|
|
1,
|
|
"Check listVlanIpRanges response"
|
|
)
|
|
self.assertTrue(
|
|
created_ip_range_response[0].forsystemvms,
|
|
"Check forsystemvms parameter in created vlan ip range"
|
|
)
|
|
|
|
def get_ip_as_number(self, ip_string):
|
|
""" Return numeric value for ip (passed as a string)
|
|
"""
|
|
packed_ip = inet_aton(ip_string)
|
|
return unpack(">L", packed_ip)[0]
|
|
|
|
def is_ip_in_range(self, start_ip, end_ip, ip_to_test):
|
|
""" Check whether ip_to_test belongs to IP range between start_ip and end_ip
|
|
"""
|
|
start = self.get_ip_as_number(start_ip)
|
|
end = self.get_ip_as_number(end_ip)
|
|
ip = self.get_ip_as_number(ip_to_test)
|
|
return start <= ip and ip <= end
|
|
|
|
def wait_for_system_vm_start(self, domain_id, systemvmtype):
|
|
""" Wait until system vm is Running
|
|
"""
|
|
def checkSystemVMUp():
|
|
response = list_ssvms(
|
|
self.apiclient,
|
|
systemvmtype=systemvmtype,
|
|
domainid=domain_id
|
|
)
|
|
if isinstance(response, list):
|
|
if response[0].state == 'Running':
|
|
return True, response[0].id
|
|
return False, None
|
|
|
|
res, systemvmId = wait_until(3, 200, checkSystemVMUp)
|
|
if not res:
|
|
raise Exception("Failed to wait for systemvm to be running")
|
|
return systemvmId
|
|
|
|
def base_system_vm(self, services, systemvmtype):
|
|
"""
|
|
Base for CPVM or SSVM depending on systemvmtype parameter
|
|
"""
|
|
|
|
# Create range for system vms
|
|
self.debug("Creating Public IP range for system vms")
|
|
self.public_ip_range = PublicIpRange.create(
|
|
self.apiclient,
|
|
services,
|
|
forsystemvms = True
|
|
)
|
|
|
|
# List Running System VM
|
|
list_systemvm_response = list_ssvms(
|
|
self.apiclient,
|
|
systemvmtype=systemvmtype,
|
|
state='Running',
|
|
domainid=self.public_ip_range.vlan.domainid
|
|
)
|
|
self.assertTrue(
|
|
isinstance(list_systemvm_response, list),
|
|
"Check list response returns a valid list"
|
|
)
|
|
self.assertEqual(
|
|
len(list_systemvm_response),
|
|
1,
|
|
"Check list response size"
|
|
)
|
|
|
|
# Delete System VM
|
|
systemvm = list_systemvm_response[0]
|
|
self.debug("Destroying System VM: %s" % systemvm.id)
|
|
cmd = destroySystemVm.destroySystemVmCmd()
|
|
cmd.id = systemvm.id
|
|
self.apiclient.destroySystemVm(cmd)
|
|
|
|
# Wait for CPVM to start
|
|
systemvm_id = self.wait_for_system_vm_start(
|
|
self.public_ip_range.vlan.domainid,
|
|
systemvmtype
|
|
)
|
|
self.assertNotEqual(
|
|
systemvm_id,
|
|
None,
|
|
"Check CPVM id is not none"
|
|
)
|
|
list_systemvm_response = list_ssvms(
|
|
self.apiclient,
|
|
id=systemvm_id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(list_systemvm_response, list),
|
|
True,
|
|
"Check list response returns a valid list"
|
|
)
|
|
systemvm_response = list_systemvm_response[0]
|
|
self.debug("System VM state after debug: %s" % systemvm_response.state)
|
|
self.assertEqual(
|
|
systemvm_response.state,
|
|
'Running',
|
|
"Check whether System VM is running or not"
|
|
)
|
|
|
|
# Verify System VM got IP in the created range
|
|
startip = services["startip"]
|
|
endip = services["endip"]
|
|
cpvm_ip = systemvm_response.publicip
|
|
|
|
self.assertTrue(
|
|
self.is_ip_in_range(startip, endip, cpvm_ip),
|
|
"Check whether System VM Public IP is in range dedicated to system vms"
|
|
)
|
|
|
|
# Disable Zone to be sure System VMs will not get recreated between calls
|
|
cmd = updateZone.updateZoneCmd()
|
|
cmd.id = self.zone.id
|
|
cmd.allocationstate = 'Disabled'
|
|
self.apiclient.updateZone(cmd)
|
|
|
|
# Delete System VM and IP range, so System VM can get IP from original ranges
|
|
self.debug("Destroying System VM: %s" % systemvm_id)
|
|
cmd = destroySystemVm.destroySystemVmCmd()
|
|
cmd.id = systemvm_id
|
|
self.apiclient.destroySystemVm(cmd)
|
|
|
|
domain_id = self.public_ip_range.vlan.domainid
|
|
self.public_ip_range.delete(self.apiclient)
|
|
|
|
# Enable Zone
|
|
cmd = updateZone.updateZoneCmd()
|
|
cmd.id = self.zone.id
|
|
cmd.allocationstate = 'Enabled'
|
|
self.apiclient.updateZone(cmd)
|
|
|
|
# Wait for System VM to start and check System VM public IP
|
|
systemvm_id = self.wait_for_system_vm_start(
|
|
domain_id,
|
|
systemvmtype
|
|
)
|
|
list_systemvm_response = list_ssvms(
|
|
self.apiclient,
|
|
id=systemvm_id
|
|
)
|
|
self.assertFalse(
|
|
self.is_ip_in_range(startip, endip, list_systemvm_response[0].publicip),
|
|
"Check System VM Public IP is not in range dedicated to system vms"
|
|
)
|
|
|
|
return True
|
|
|
|
def exists_public_ip_range_for_system_vms(self, zoneid):
|
|
"""
|
|
Return True if there exists a public IP range dedicated for system vms in zoneid
|
|
"""
|
|
existing_ip_ranges_response = PublicIpRange.list(
|
|
self.apiclient,
|
|
zoneid=zoneid
|
|
)
|
|
for r in existing_ip_ranges_response:
|
|
if r.forsystemvms:
|
|
return True
|
|
return False
|
|
|
|
@attr(tags = ["advanced", "publiciprange", "dedicate", "release"], required_hardware="false")
|
|
def test_dedicate_public_ip_range_for_system_vms_01_ssvm(self):
|
|
"""Test SSVM Public IP
|
|
"""
|
|
self.debug("Precondition: No public IP range dedicated for system vms in the environment")
|
|
if self.exists_public_ip_range_for_system_vms(self.services["zoneid"]):
|
|
self.skipTest("An existing IP range defined for system vms, aborting test")
|
|
|
|
services = {
|
|
"gateway":"192.168.100.1",
|
|
"netmask":"255.255.255.0",
|
|
"startip":"192.168.100.2",
|
|
"endip":"192.168.100.200",
|
|
"forvirtualnetwork":self.services["forvirtualnetwork"],
|
|
"zoneid":self.services["zoneid"],
|
|
"vlan":self.services["vlan"]
|
|
}
|
|
|
|
try:
|
|
self.base_system_vm(
|
|
services,
|
|
'secondarystoragevm'
|
|
)
|
|
except Exception:
|
|
self.delete_range()
|
|
|
|
return
|
|
|
|
@attr(tags = ["advanced", "publiciprange", "dedicate", "release"], required_hardware="false")
|
|
def test_dedicate_public_ip_range_for_system_vms_02_cpvm(self):
|
|
"""Test CPVM Public IP
|
|
"""
|
|
self.debug("Precondition: No public IP range dedicated for system vms in the environment")
|
|
if self.exists_public_ip_range_for_system_vms(self.services["zoneid"]):
|
|
self.skipTest("An existing IP range defined for system vms, aborting test")
|
|
|
|
services = {
|
|
"gateway":"192.168.200.1",
|
|
"netmask":"255.255.255.0",
|
|
"startip":"192.168.200.2",
|
|
"endip":"192.168.200.200",
|
|
"forvirtualnetwork":self.services["forvirtualnetwork"],
|
|
"zoneid":self.services["zoneid"],
|
|
"vlan":self.services["vlan"]
|
|
}
|
|
|
|
try:
|
|
self.base_system_vm(
|
|
services,
|
|
'consoleproxy'
|
|
)
|
|
except Exception:
|
|
self.delete_range()
|
|
|
|
return
|
|
|
|
def delete_range(self):
|
|
|
|
# List System VMs
|
|
system_vms = list_ssvms(
|
|
self.apiclient,
|
|
)
|
|
|
|
# Disable Zone to be sure System VMs will not get recreated between calls
|
|
cmd = updateZone.updateZoneCmd()
|
|
cmd.id = self.zone.id
|
|
cmd.allocationstate = 'Disabled'
|
|
self.apiclient.updateZone(cmd)
|
|
|
|
# Delete System VM and IP range, so System VM can get IP from original ranges
|
|
if system_vms:
|
|
for v in system_vms:
|
|
self.debug("Destroying System VM: %s" % v.id)
|
|
cmd = destroySystemVm.destroySystemVmCmd()
|
|
cmd.id = v.id
|
|
self.apiclient.destroySystemVm(cmd)
|
|
|
|
self.public_ip_range.delete(self.apiclient)
|
|
|
|
# Enable Zone
|
|
cmd = updateZone.updateZoneCmd()
|
|
cmd.id = self.zone.id
|
|
cmd.allocationstate = 'Enabled'
|
|
self.apiclient.updateZone(cmd)
|