The launcher's leaked resource cleanup method would overwrite the list of potential leaked resources after each endpoint; this means that only the last endpoint to run would actually have its resources cleaned up. Correct this by keeping a list of potential leaks indexed by endpoint. Change-Id: I961cb53f53ccf5fc39e467e1ddde3034a46f1952
216 lines
7.5 KiB
Python
216 lines
7.5 KiB
Python
# Copyright 2024 Acme Gating, LLC
|
|
#
|
|
# Licensed 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.
|
|
|
|
import os
|
|
import time
|
|
|
|
import fixtures
|
|
|
|
from zuul.driver.openstack import OpenstackDriver
|
|
import zuul.driver.openstack.openstackendpoint
|
|
|
|
from tests.fake_openstack import (
|
|
FakeOpenstackCloud,
|
|
FakeOpenstackFloatingIp,
|
|
FakeOpenstackPort,
|
|
FakeOpenstackProviderEndpoint,
|
|
)
|
|
from tests.base import (
|
|
FIXTURE_DIR,
|
|
ZuulTestCase,
|
|
driver_config,
|
|
iterate_timeout,
|
|
return_data,
|
|
simple_layout,
|
|
)
|
|
from tests.unit.test_launcher import ImageMocksFixture
|
|
from tests.unit.test_cloud_driver import BaseCloudDriverTest
|
|
|
|
|
|
class BaseOpenstackDriverTest(ZuulTestCase):
|
|
cloud_test_image_format = 'qcow2'
|
|
cloud_test_provider_name = 'openstack-main'
|
|
config_file = 'zuul-connections-nodepool.conf'
|
|
debian_return_data = {
|
|
'zuul': {
|
|
'artifacts': [
|
|
{
|
|
'name': 'raw image',
|
|
'url': 'http://example.com/image.raw',
|
|
'metadata': {
|
|
'type': 'zuul_image',
|
|
'image_name': 'debian-local',
|
|
'format': 'qcow2',
|
|
'sha256': ('59984dd82f51edb3777b969739a92780'
|
|
'a520bb314b8d64b294d5de976bd8efb9'),
|
|
'md5sum': '262278e1632567a907e4604e9edd2e83',
|
|
}
|
|
},
|
|
]
|
|
}
|
|
}
|
|
openstack_needs_floating_ip = False
|
|
openstack_auto_attach_floating_ip = True
|
|
|
|
def _makeFakeCloud(self, region):
|
|
fake_cloud = FakeOpenstackCloud(
|
|
region,
|
|
needs_floating_ip=self.openstack_needs_floating_ip,
|
|
auto_attach_floating_ip=self.openstack_auto_attach_floating_ip,
|
|
)
|
|
fake_cloud.max_instances =\
|
|
self.test_config.driver.openstack.get('max_instances', 100)
|
|
fake_cloud.max_cores =\
|
|
self.test_config.driver.openstack.get('max_cores', 100)
|
|
fake_cloud.max_ram =\
|
|
self.test_config.driver.openstack.get('max_ram', 1000000)
|
|
fake_cloud.max_volumes =\
|
|
self.test_config.driver.openstack.get('max_volumes', 100)
|
|
fake_cloud.max_volume_gb =\
|
|
self.test_config.driver.openstack.get('max_volume_gb', 100)
|
|
self.fake_cloud[region] = fake_cloud
|
|
|
|
def setUp(self):
|
|
self.initTestConfig()
|
|
self.useFixture(ImageMocksFixture())
|
|
clouds_yaml = os.path.join(FIXTURE_DIR, 'clouds.yaml')
|
|
self.useFixture(
|
|
fixtures.EnvironmentVariable('OS_CLIENT_CONFIG_FILE', clouds_yaml))
|
|
|
|
self.fake_cloud = {}
|
|
self._makeFakeCloud(None)
|
|
self._makeFakeCloud('region2')
|
|
self.patch(OpenstackDriver, '_endpoint_class',
|
|
FakeOpenstackProviderEndpoint)
|
|
self.patch(FakeOpenstackProviderEndpoint,
|
|
'_fake_cloud', self.fake_cloud)
|
|
self.patch(zuul.driver.openstack.openstackendpoint,
|
|
'CACHE_TTL', 1)
|
|
super().setUp()
|
|
|
|
|
|
class TestOpenstackDriver(BaseOpenstackDriverTest, BaseCloudDriverTest):
|
|
def _assertProviderNodeAttributes(self, pnode):
|
|
super()._assertProviderNodeAttributes(pnode)
|
|
self.assertEqual('fakecloud', pnode.cloud)
|
|
self.assertEqual('region1', pnode.region)
|
|
if checks := self.test_config.driver.openstack.get('node_checks'):
|
|
checks(self, pnode)
|
|
|
|
@simple_layout('layouts/openstack/nodepool.yaml', enable_nodepool=True)
|
|
def test_openstack_node_lifecycle(self):
|
|
self._test_node_lifecycle('debian-normal')
|
|
|
|
def check_more_attrs(self, pnode):
|
|
self.assertEqual('foo', pnode.az)
|
|
|
|
@simple_layout('layouts/openstack/more.yaml', enable_nodepool=True)
|
|
@driver_config('openstack', node_checks=check_more_attrs)
|
|
def test_openstack_node_lifecycle_more(self):
|
|
# Test with more options than the normal test
|
|
self._test_node_lifecycle('debian-normal')
|
|
|
|
@simple_layout('layouts/openstack/nodepool.yaml', enable_nodepool=True)
|
|
@driver_config('openstack', max_cores=4)
|
|
def test_openstack_quota(self):
|
|
self._test_quota('debian-normal')
|
|
|
|
@simple_layout('layouts/openstack/resource-limits.yaml',
|
|
enable_nodepool=True)
|
|
def test_openstack_resource_limits(self):
|
|
self._test_quota('debian-normal')
|
|
|
|
@simple_layout('layouts/openstack/nodepool-image.yaml',
|
|
enable_nodepool=True)
|
|
@return_data(
|
|
'build-debian-local-image',
|
|
'refs/heads/master',
|
|
BaseOpenstackDriverTest.debian_return_data,
|
|
)
|
|
def test_openstack_diskimage(self):
|
|
self._test_diskimage()
|
|
|
|
# Openstack-driver specific tests
|
|
|
|
@simple_layout('layouts/openstack/nodepool-multi.yaml',
|
|
enable_nodepool=True)
|
|
def test_openstack_resource_cleanup(self):
|
|
self.waitUntilSettled()
|
|
self.launcher.cleanup_worker.INTERVAL = 1
|
|
conn = self.fake_cloud[None]._getConnection()
|
|
system_id = self.launcher.system.system_id
|
|
tags = {
|
|
'zuul_system_id': system_id,
|
|
'zuul_node_uuid': '0000000042',
|
|
}
|
|
conn.create_server(
|
|
name="test",
|
|
meta=tags,
|
|
)
|
|
self.assertEqual(1, len(conn.list_servers()))
|
|
|
|
fip = FakeOpenstackFloatingIp(
|
|
id='42',
|
|
floating_ip_address='fake',
|
|
status='ACTIVE',
|
|
)
|
|
conn.cloud.floating_ips.append(fip)
|
|
self.assertEqual(1, len(conn.list_floating_ips()))
|
|
|
|
port = FakeOpenstackPort(
|
|
id='43',
|
|
status='DOWN',
|
|
device_owner='compute:foo',
|
|
)
|
|
conn.cloud.ports.append(port)
|
|
self.assertEqual(1, len(conn.list_ports()))
|
|
|
|
self.log.debug("Start cleanup worker")
|
|
self.launcher.cleanup_worker.start()
|
|
|
|
for _ in iterate_timeout(30, 'instance deletion'):
|
|
if not conn.list_servers():
|
|
break
|
|
time.sleep(1)
|
|
for _ in iterate_timeout(30, 'fip deletion'):
|
|
if not conn.list_floating_ips():
|
|
break
|
|
time.sleep(1)
|
|
for _ in iterate_timeout(30, 'port deletion'):
|
|
if not conn.list_ports():
|
|
break
|
|
time.sleep(1)
|
|
|
|
|
|
class TestOpenstackDriverFloatingIp(BaseOpenstackDriverTest,
|
|
BaseCloudDriverTest):
|
|
# This test is for nova-net clouds with floating ips that require
|
|
# manual attachment.
|
|
openstack_needs_floating_ip = True
|
|
openstack_auto_attach_floating_ip = False
|
|
|
|
@simple_layout('layouts/openstack/nodepool.yaml', enable_nodepool=True)
|
|
def test_openstack_fip(self):
|
|
self._test_node_lifecycle('debian-normal')
|
|
|
|
|
|
class TestOpenstackDriverAutoAttachFloatingIp(BaseOpenstackDriverTest,
|
|
BaseCloudDriverTest):
|
|
openstack_needs_floating_ip = True
|
|
openstack_auto_attach_floating_ip = True
|
|
|
|
@simple_layout('layouts/openstack/nodepool.yaml', enable_nodepool=True)
|
|
def test_openstack_auto_attach_fip(self):
|
|
self._test_node_lifecycle('debian-normal')
|