zuul/tests/unit/test_cloud_driver.py
James E. Blair 687f683199 Launcher: fix deleting servers
The openstack and aws drivers both had some minor errors preventing
instance deletion from working.  Fix those and add test assertions.

Change-Id: I4724ee3e17820dbe0a4029409f49190924b17f83
2024-10-28 15:40:30 -07:00

124 lines
4.4 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 testtools
from kazoo.exceptions import NoNodeError
from zuul import model
from zuul.launcher.client import LauncherClient
from tests.base import (
ZuulTestCase,
iterate_timeout,
)
class BaseCloudDriverTest(ZuulTestCase):
cloud_test_connection_type = 'ssh'
cloud_test_image_format = ''
cloud_test_provider_name = ''
def _getEndpoint(self):
# Use the launcher provider so that we're using the same ttl
# method caches.
for provider in self.launcher.tenant_providers['tenant-one']:
if provider.name == self.cloud_test_provider_name:
return provider.getEndpoint()
def _assertProviderNodeAttributes(self, pnode):
self.assertEqual(pnode.connection_type,
self.cloud_test_connection_type)
self.assertIsNotNone(pnode.interface_ip)
def _test_node_lifecycle(self, label):
# Call this in a test to run a node lifecycle
for _ in iterate_timeout(
30, "scheduler and launcher to have the same layout"):
if (self.scheds.first.sched.local_layout_state.get("tenant-one") ==
self.launcher.local_layout_state.get("tenant-one")):
break
endpoint = self._getEndpoint()
nodeset = model.NodeSet()
nodeset.addNode(model.Node("node", label))
ctx = self.createZKContext(None)
request = self.requestNodes([n.label for n in nodeset.getNodes()])
client = LauncherClient(self.zk_client, None)
request = client.getRequest(request.uuid)
self.assertEqual(request.state, model.NodesetRequest.State.FULFILLED)
self.assertEqual(len(request.nodes), 1)
client.acceptNodeset(request, nodeset)
self.waitUntilSettled()
with testtools.ExpectedException(NoNodeError):
# Request should be gone
request.refresh(ctx)
for node in nodeset.getNodes():
pnode = node._provider_node
self.assertIsNotNone(pnode)
self.assertTrue(pnode.hasLock())
self._assertProviderNodeAttributes(pnode)
self.assertGreater(len(list(endpoint.listInstances())), 0)
client.useNodeset(nodeset)
self.waitUntilSettled()
for node in nodeset.getNodes():
pnode = node._provider_node
self.assertTrue(pnode.hasLock())
self.assertTrue(pnode.state, pnode.State.IN_USE)
client.returnNodeset(nodeset)
self.waitUntilSettled()
for node in nodeset.getNodes():
pnode = node._provider_node
self.assertFalse(pnode.hasLock())
self.assertTrue(pnode.state, pnode.State.USED)
for _ in iterate_timeout(60, "node to be deleted"):
try:
pnode.refresh(ctx)
except NoNodeError:
break
# Iterate here because the aws driver (at least) performs
# delayed async deletes.
for _ in iterate_timeout(60, "instances to be deleted"):
if len(list(endpoint.listInstances())) == 0:
break
def _test_diskimage(self):
self.waitUntilSettled()
self.assertHistory([
dict(name='build-debian-local-image', result='SUCCESS'),
], ordered=False)
name = 'review.example.com%2Forg%2Fcommon-config/debian-local'
artifacts = self.launcher.image_build_registry.\
getArtifactsForImage(name)
self.assertEqual(1, len(artifacts))
self.assertEqual(self.cloud_test_image_format, artifacts[0].format)
self.assertTrue(artifacts[0].validated)
uploads = self.launcher.image_upload_registry.getUploadsForImage(
name)
self.assertEqual(1, len(uploads))
self.assertEqual(artifacts[0].uuid, uploads[0].artifact_uuid)
self.assertIsNotNone(uploads[0].external_id)
self.assertTrue(uploads[0].validated)