Adding the disable feature
This feature allow the disable of most of the project resources in some cases the admin want to disable the project and wait for period of time before deleting the resources just in case some resources are still usable or need to be moved to another project for nova the disable will stop the servers for neutron it will change the admin_state_up to false which will change the status of resource to down for glance it will deactivate the images for swift it will remove the read/write acls to container for octaivia chenge the admin_state_up to false making the status of loadbalancer down for cinder it will change the volume to readonly for the resources that dont have a way of disabling the resource it will just log a warning Change-Id: Ic2af6ad1ffb1e749a3d1ba687950264b5098bcdb
This commit is contained in:
parent
3ca9f412b4
commit
39a159f8c7
|
@ -72,6 +72,11 @@ def create_argument_parser():
|
|||
"--os-identity-api-version", default=3,
|
||||
help="Identity API version, default=3"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--disable-only", action="store_true",
|
||||
help="Disable resources of the project rather than purging them. "
|
||||
"Useful if you want to keep the resources but disable them."
|
||||
)
|
||||
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument(
|
||||
|
@ -164,7 +169,9 @@ class CredentialsManager(object):
|
|||
def runner(resource_mngr, options, exit):
|
||||
try:
|
||||
|
||||
if not (options.dry_run or options.resource):
|
||||
if not (options.dry_run or
|
||||
options.resource or
|
||||
options.disable_only):
|
||||
resource_mngr.wait_for_check_prerequisite(exit)
|
||||
|
||||
for resource in resource_mngr.list():
|
||||
|
@ -172,18 +179,27 @@ def runner(resource_mngr, options, exit):
|
|||
if exit.is_set():
|
||||
return
|
||||
|
||||
if resource_mngr.should_delete(resource):
|
||||
resource_func_to_call = None
|
||||
if options.disable_only:
|
||||
resource_func_to_call = resource_mngr.disable
|
||||
logging.info("Going to disable resource %s",
|
||||
resource_mngr.to_str(resource))
|
||||
|
||||
elif resource_mngr.should_delete(resource):
|
||||
resource_func_to_call = resource_mngr.delete
|
||||
logging.info("Going to delete %s",
|
||||
resource_mngr.to_str(resource))
|
||||
|
||||
# If we are in dry run mode, don't actually delete the resource
|
||||
if resource_func_to_call:
|
||||
# If we are in dry run mode, don't actually delete/disable
|
||||
# the resource
|
||||
if options.dry_run:
|
||||
continue
|
||||
|
||||
# If we want to delete only specific resources, many things
|
||||
# can go wrong, so we basically ignore all exceptions.
|
||||
# If we want to delete/disable only specific resources, many
|
||||
# things can go wrong, so we basically ignore all exceptions.
|
||||
exc = os_exceptions.OpenStackCloudException
|
||||
utils.call_and_ignore_exc(exc, resource_mngr.delete, resource)
|
||||
utils.call_and_ignore_exc(exc, resource_func_to_call, resource)
|
||||
|
||||
except Exception as exc:
|
||||
log = logging.error
|
||||
|
|
|
@ -136,6 +136,14 @@ class ServiceResource(six.with_metaclass(CodingStyleMixin,
|
|||
def delete(self, resource):
|
||||
raise NotImplementedError
|
||||
|
||||
def disable(self, resource):
|
||||
msg = "The disable feature is not supported for %s, No action will" \
|
||||
"be taken against the resource(id=%s, name=%s)."
|
||||
logging.warning(
|
||||
msg, self.__class__.__name__,
|
||||
resource.get('id'), resource.get('name')
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@abc.abstractmethod
|
||||
def to_str(resource):
|
||||
|
|
|
@ -59,6 +59,14 @@ class Volumes(base.ServiceResource):
|
|||
def delete(self, resource):
|
||||
self.cloud.delete_volume(resource['id'])
|
||||
|
||||
def disable(self, resource):
|
||||
# Since there is no disable for volume setting it to readonly
|
||||
# is good enough so no update on it
|
||||
self.cloud.update_volume(
|
||||
resource['id'],
|
||||
metadata={'readonly': 'true'}
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource):
|
||||
return "Volume (id='{}', name='{}')".format(
|
||||
|
|
|
@ -53,6 +53,9 @@ class Volumes(base.ServiceResource):
|
|||
def delete(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
def disable(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource: Dict[str, Any]) -> str:
|
||||
...
|
||||
|
|
|
@ -43,6 +43,9 @@ class Images(base.ServiceResource, ListImagesMixin):
|
|||
def delete(self, resource):
|
||||
self.cloud.delete_image(resource['id'])
|
||||
|
||||
def disable(self, resource):
|
||||
self.cloud.image.deactivate_image(resource['id'])
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource):
|
||||
return "Image (id='{}', name='{}')".format(
|
||||
|
|
|
@ -32,6 +32,9 @@ class Images(base.ServiceResource, ListImagesMixin):
|
|||
def delete(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
def disable(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource: Dict[str, Any]) -> str:
|
||||
...
|
||||
|
|
|
@ -27,6 +27,12 @@ class FloatingIPs(base.ServiceResource):
|
|||
def delete(self, resource):
|
||||
self.cloud.delete_floating_ip(resource['id'])
|
||||
|
||||
def disable(self, resource):
|
||||
self.cloud.network.update_ip(
|
||||
resource['id'],
|
||||
port_id=None,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource):
|
||||
return "Floating IP (id='{}')".format(resource['id'])
|
||||
|
@ -76,6 +82,12 @@ class Routers(base.ServiceResource):
|
|||
def delete(self, resource):
|
||||
self.cloud.delete_router(resource['id'])
|
||||
|
||||
def disable(self, resource):
|
||||
self.cloud.update_router(
|
||||
resource['id'],
|
||||
admin_state_up=False
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource):
|
||||
return "Router (id='{}', name='{}')".format(
|
||||
|
@ -97,6 +109,9 @@ class Ports(base.ServiceResource):
|
|||
def delete(self, resource):
|
||||
self.cloud.delete_port(resource['id'])
|
||||
|
||||
def disable(self, resource):
|
||||
self.cloud.update_port(resource['id'], admin_state_up=False)
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource):
|
||||
return "Port (id='{}', network_id='{}, device_owner='{}')'".format(
|
||||
|
@ -128,6 +143,9 @@ class Networks(base.ServiceResource):
|
|||
def delete(self, resource):
|
||||
self.cloud.delete_network(resource['id'])
|
||||
|
||||
def disable(self, resource):
|
||||
self.cloud.update_network(resource['id'], admin_state_up=False)
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource):
|
||||
return "Network (id='{}', name='{}')".format(
|
||||
|
|
|
@ -26,6 +26,9 @@ class FloatingIPs(base.ServiceResource):
|
|||
def delete(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
def disable(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource: Dict[str, Any]) -> str:
|
||||
...
|
||||
|
@ -56,6 +59,9 @@ class Routers(base.ServiceResource):
|
|||
def delete(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
def disable(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource: Dict[str, Any]) -> str:
|
||||
...
|
||||
|
@ -68,6 +74,9 @@ class Ports(base.ServiceResource):
|
|||
def delete(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
def disable(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource: Dict[str, Any]) -> str:
|
||||
...
|
||||
|
@ -83,6 +92,9 @@ class Networks(base.ServiceResource):
|
|||
def delete(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
def disable(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource: Dict[str, Any]) -> str:
|
||||
...
|
||||
|
|
|
@ -21,6 +21,9 @@ class Servers(base.ServiceResource):
|
|||
def delete(self, resource):
|
||||
self.cloud.delete_server(resource['id'])
|
||||
|
||||
def disable(self, resource):
|
||||
self.cloud.compute.stop_server(resource['id'])
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource):
|
||||
return "VM (id='{}', name='{}')".format(
|
||||
|
|
|
@ -23,6 +23,9 @@ class Servers(base.ServiceResource):
|
|||
def delete(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
def disable(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource: Dict[str, Any]) -> str:
|
||||
...
|
||||
|
|
|
@ -25,6 +25,12 @@ class LoadBalancers(base.ServiceResource):
|
|||
self.cloud.load_balancer.delete_load_balancer(
|
||||
resource['id'], cascade=True)
|
||||
|
||||
def disable(self, resource):
|
||||
self.cloud.load_balancer.update_load_balancer(
|
||||
resource['id'],
|
||||
admin_state_up=False
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource):
|
||||
return "Octavia LoadBalancer (id='{}', name='{}')".format(
|
||||
|
|
|
@ -23,6 +23,9 @@ class LoadBalancers(base.ServiceResource):
|
|||
def delete(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
def disable(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource: Dict[str, Any]) -> str:
|
||||
...
|
||||
|
|
|
@ -62,6 +62,14 @@ class Containers(base.ServiceResource, ListObjectsMixin):
|
|||
def delete(self, resource):
|
||||
self.cloud.delete_container(urllib_parse.quote(resource['name']))
|
||||
|
||||
def disable(self, resource):
|
||||
# There is no disable for the swift container just removing the
|
||||
# write/read access to the conatianer, so only admin can access
|
||||
self.cloud.object_store.set_container_metadata(
|
||||
urllib_parse.quote(resource['name']),
|
||||
write_acl=None, read_acl=None
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource):
|
||||
return "Container (name='{}')".format(resource['name'])
|
||||
|
|
|
@ -49,6 +49,9 @@ class Containers(base.ServiceResource, ListObjectsMixin):
|
|||
def delete(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
def disable(self, resource: Dict[str, Any]) -> None:
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def to_str(resource: Dict[str, Any]) -> str:
|
||||
...
|
||||
|
|
|
@ -32,6 +32,11 @@ class TestBackups(unittest.TestCase):
|
|||
self.assertIsNone(cinder.Backups(self.creds_manager).delete(backup))
|
||||
self.cloud.delete_volume_backup.assert_called_once_with(backup['id'])
|
||||
|
||||
def test_disable(self):
|
||||
backup = mock.MagicMock()
|
||||
with self.assertLogs(level='WARNING'):
|
||||
cinder.Backups(self.creds_manager).disable(backup)
|
||||
|
||||
def test_to_string(self):
|
||||
backup = mock.MagicMock()
|
||||
self.assertIn("Volume Backup",
|
||||
|
@ -55,6 +60,11 @@ class TestSnapshots(unittest.TestCase):
|
|||
self.cloud.delete_volume_snapshot.assert_called_once_with(
|
||||
snapshot['id'])
|
||||
|
||||
def test_disable(self):
|
||||
snapshot = mock.MagicMock()
|
||||
with self.assertLogs(level='WARNING'):
|
||||
cinder.Snapshots(self.creds_manager).disable(snapshot)
|
||||
|
||||
def test_to_string(self):
|
||||
snapshot = mock.MagicMock()
|
||||
self.assertIn("Volume Snapshot ",
|
||||
|
@ -97,6 +107,14 @@ class TestVolumes(unittest.TestCase):
|
|||
self.assertIsNone(cinder.Volumes(self.creds_manager).delete(volume))
|
||||
self.cloud.delete_volume.assert_called_once_with(volume['id'])
|
||||
|
||||
def test_disable(self):
|
||||
volume = mock.MagicMock()
|
||||
cinder.Volumes(self.creds_manager).disable(volume)
|
||||
self.cloud.update_volume.assert_called_once_with(
|
||||
volume['id'],
|
||||
metadata={'readonly': 'true'}
|
||||
)
|
||||
|
||||
def test_to_string(self):
|
||||
volume = mock.MagicMock()
|
||||
self.assertIn("Volume ",
|
||||
|
|
|
@ -38,6 +38,11 @@ class TestZones(unittest.TestCase):
|
|||
self.assertIsNone(designate.Zones(self.creds_manager).delete(zone))
|
||||
self.cloud.delete_zone.assert_called_once_with(zone['id'])
|
||||
|
||||
def test_disable(self):
|
||||
zone = mock.MagicMock()
|
||||
with self.assertLogs(level='WARNING'):
|
||||
designate.Zones(self.creds_manager).disable(zone)
|
||||
|
||||
def test_to_string(self):
|
||||
stack = mock.MagicMock()
|
||||
self.assertIn("Designate Zone",
|
||||
|
|
|
@ -79,6 +79,13 @@ class TestImages(unittest.TestCase):
|
|||
self.assertIsNone(glance.Images(self.creds_manager).delete(image))
|
||||
self.cloud.delete_image.assert_called_once_with(image['id'])
|
||||
|
||||
def test_disable(self):
|
||||
image = mock.MagicMock()
|
||||
self.assertIsNone(glance.Images(self.creds_manager).disable(image))
|
||||
self.cloud.image.deactivate_image.assert_called_once_with(
|
||||
image['id']
|
||||
)
|
||||
|
||||
def test_to_string(self):
|
||||
image = mock.MagicMock()
|
||||
self.assertIn("Image (",
|
||||
|
|
|
@ -38,6 +38,11 @@ class TestStacks(unittest.TestCase):
|
|||
self.assertIsNone(heat.Stacks(self.creds_manager).delete(stack))
|
||||
self.cloud.delete_stack.assert_called_once_with(stack['id'], wait=True)
|
||||
|
||||
def test_disable(self):
|
||||
stack = mock.MagicMock()
|
||||
with self.assertLogs(level='WARNING'):
|
||||
heat.Stacks(self.creds_manager).disable(stack)
|
||||
|
||||
def test_to_string(self):
|
||||
stack = mock.MagicMock()
|
||||
self.assertIn("Heat Stack",
|
||||
|
|
|
@ -47,6 +47,14 @@ class TestFloatingIPs(unittest.TestCase):
|
|||
self.cloud.delete_floating_ip.assert_called_once_with(
|
||||
fip['id'])
|
||||
|
||||
def test_disable(self):
|
||||
fip = mock.MagicMock()
|
||||
self.assertIsNone(neutron.FloatingIPs(self.creds_manager).disable(
|
||||
fip
|
||||
))
|
||||
self.cloud.network.update_ip.assert_called_once_with(
|
||||
fip['id'], port_id=None)
|
||||
|
||||
def test_to_string(self):
|
||||
fip = mock.MagicMock()
|
||||
self.assertIn("Floating IP ",
|
||||
|
@ -93,6 +101,13 @@ class TestRouterInterfaces(unittest.TestCase):
|
|||
port_id=iface['id']
|
||||
)
|
||||
|
||||
def test_disable(self):
|
||||
iface = mock.MagicMock()
|
||||
with self.assertLogs(level='WARNING'):
|
||||
neutron.RouterInterfaces(self.creds_manager).disable(
|
||||
iface
|
||||
)
|
||||
|
||||
def test_to_string(self):
|
||||
iface = mock.MagicMock()
|
||||
self.assertIn(
|
||||
|
@ -131,6 +146,14 @@ class TestRouters(unittest.TestCase):
|
|||
self.assertIsNone(neutron.Routers(self.creds_manager).delete(router))
|
||||
self.cloud.delete_router.assert_called_once_with(router['id'])
|
||||
|
||||
def test_disable(self):
|
||||
router = mock.MagicMock()
|
||||
self.assertIsNone(neutron.Routers(self.creds_manager).disable(router))
|
||||
self.cloud.update_router.assert_called_once_with(
|
||||
router['id'],
|
||||
admin_state_up=False
|
||||
)
|
||||
|
||||
def test_to_string(self):
|
||||
router = mock.MagicMock()
|
||||
self.assertIn("Router (",
|
||||
|
@ -159,6 +182,14 @@ class TestPorts(unittest.TestCase):
|
|||
self.assertIsNone(neutron.Ports(self.creds_manager).delete(port))
|
||||
self.cloud.delete_port.assert_called_once_with(port['id'])
|
||||
|
||||
def test_disable(self):
|
||||
port = mock.MagicMock()
|
||||
self.assertIsNone(neutron.Ports(self.creds_manager).disable(port))
|
||||
self.cloud.update_port.assert_called_once_with(
|
||||
port['id'],
|
||||
admin_state_up=False
|
||||
)
|
||||
|
||||
def test_to_string(self):
|
||||
port = mock.MagicMock()
|
||||
self.assertIn("Port (",
|
||||
|
@ -203,6 +234,14 @@ class TestNetworks(unittest.TestCase):
|
|||
self.assertIsNone(neutron.Networks(self.creds_manager).delete(nw))
|
||||
self.cloud.delete_network.assert_called_once_with(nw['id'])
|
||||
|
||||
def test_disable(self):
|
||||
nw = mock.MagicMock()
|
||||
self.assertIsNone(neutron.Networks(self.creds_manager).disable(nw))
|
||||
self.cloud.update_network.assert_called_once_with(
|
||||
nw['id'],
|
||||
admin_state_up=False
|
||||
)
|
||||
|
||||
def test_to_string(self):
|
||||
nw = mock.MagicMock()
|
||||
self.assertIn("Network (",
|
||||
|
@ -230,6 +269,11 @@ class TestSecurityGroups(unittest.TestCase):
|
|||
neutron.SecurityGroups(self.creds_manager).delete(sg))
|
||||
self.cloud.delete_security_group.assert_called_once_with(sg['id'])
|
||||
|
||||
def test_disable(self):
|
||||
sg = mock.MagicMock()
|
||||
with self.assertLogs(level='WARNING'):
|
||||
neutron.SecurityGroups(self.creds_manager).disable(sg)
|
||||
|
||||
def test_to_string(self):
|
||||
sg = mock.MagicMock()
|
||||
self.assertIn("Security Group (",
|
||||
|
|
|
@ -32,6 +32,11 @@ class TestServers(unittest.TestCase):
|
|||
self.assertIsNone(nova.Servers(self.creds_manager).delete(server))
|
||||
self.cloud.delete_server.assert_called_once_with(server['id'])
|
||||
|
||||
def test_disable(self):
|
||||
server = mock.MagicMock()
|
||||
self.assertIsNone(nova.Servers(self.creds_manager).disable(server))
|
||||
self.cloud.compute.stop_server.assert_called_once_with(server['id'])
|
||||
|
||||
def test_to_string(self):
|
||||
server = mock.MagicMock()
|
||||
self.assertIn("VM (",
|
||||
|
|
|
@ -44,6 +44,13 @@ class TestLoadBalancers(unittest.TestCase):
|
|||
(self.cloud.load_balancer.delete_load_balancer
|
||||
.assert_called_once_with(lb['id'], cascade=True))
|
||||
|
||||
def test_disable(self):
|
||||
lb = mock.MagicMock()
|
||||
self.assertIsNone(octavia.LoadBalancers(self.creds_manager).disable(
|
||||
lb))
|
||||
(self.cloud.load_balancer.update_load_balancer
|
||||
.assert_called_once_with(lb['id'], admin_state_up=False))
|
||||
|
||||
def test_to_string(self):
|
||||
stack = mock.MagicMock()
|
||||
self.assertIn("Octavia LoadBalancer",
|
||||
|
|
|
@ -89,6 +89,11 @@ class TestObjects(unittest.TestCase):
|
|||
urllib_parse.quote(obj['name'])
|
||||
)
|
||||
|
||||
def test_disable(self):
|
||||
obj = {'name': 'toto', 'container_name': 'foo'}
|
||||
with self.assertLogs(level='WARNING'):
|
||||
swift.Objects(self.creds_manager).disable(obj)
|
||||
|
||||
def test_to_string(self):
|
||||
obj = mock.MagicMock()
|
||||
self.assertIn("Object '",
|
||||
|
@ -128,6 +133,17 @@ class TestContainers(unittest.TestCase):
|
|||
urllib_parse.quote(cont['name'])
|
||||
)
|
||||
|
||||
def test_disable(self):
|
||||
cont = {'bytes': 8,
|
||||
'count': 2,
|
||||
'last_modified': '2019-06-05T15:20:59.450120',
|
||||
'name': 'Pouet éêù #'}
|
||||
self.assertIsNone(swift.Containers(self.creds_manager).disable(cont))
|
||||
self.cloud.object_store.set_container_metadata.assert_called_once_with(
|
||||
urllib_parse.quote(cont['name']),
|
||||
read_acl=None, write_acl=None
|
||||
)
|
||||
|
||||
def test_to_string(self):
|
||||
container = mock.MagicMock()
|
||||
self.assertIn("Container (",
|
||||
|
|
|
@ -74,10 +74,10 @@ class TestFunctions(unittest.TestCase):
|
|||
self.assertEqual('foo', options.purge_project)
|
||||
self.assertEqual(['Networks', 'Volumes'], options.resource)
|
||||
|
||||
def test_runner(self):
|
||||
def test_runner_delete(self):
|
||||
resources = [mock.Mock(), mock.Mock(), mock.Mock()]
|
||||
resource_manager = mock.Mock(list=mock.Mock(return_value=resources))
|
||||
options = mock.Mock(dry_run=False, resource=False)
|
||||
options = mock.Mock(dry_run=False, resource=False, disable_only=False)
|
||||
exit = mock.Mock(is_set=mock.Mock(side_effect=[False, False, True]))
|
||||
|
||||
main.runner(resource_manager, options, exit)
|
||||
|
@ -95,10 +95,43 @@ class TestFunctions(unittest.TestCase):
|
|||
resource_manager.delete.call_args_list
|
||||
)
|
||||
|
||||
def test_runner_dry_run(self):
|
||||
def test_runner_disable(self):
|
||||
resources = [mock.Mock(), mock.Mock(), mock.Mock()]
|
||||
resource_manager = mock.Mock(list=mock.Mock(return_value=resources))
|
||||
options = mock.Mock(dry_run=False, resource=False, disable_only=True)
|
||||
exit = mock.Mock(is_set=mock.Mock(side_effect=[False, False, True]))
|
||||
|
||||
main.runner(resource_manager, options, exit)
|
||||
|
||||
resource_manager.list.assert_called_once_with()
|
||||
resource_manager.wait_for_check_prerequisite.assert_not_called()
|
||||
resource_manager.should_delete.assert_not_called()
|
||||
resource_manager.delete.assert_not_called()
|
||||
self.assertEqual(2, resource_manager.disable.call_count)
|
||||
self.assertEqual(
|
||||
[mock.call(resources[0]), mock.call(resources[1])],
|
||||
resource_manager.disable.call_args_list
|
||||
)
|
||||
|
||||
def test_runner_disable_dry_run(self):
|
||||
resources = [mock.Mock(), mock.Mock(), mock.Mock()]
|
||||
resource_manager = mock.Mock(list=mock.Mock(return_value=resources))
|
||||
options = mock.Mock(dry_run=True, resource=False, disable_only=True)
|
||||
exit = mock.Mock(is_set=mock.Mock(side_effect=[False, False, True]))
|
||||
|
||||
main.runner(resource_manager, options, exit)
|
||||
|
||||
resource_manager.list.assert_called_once_with()
|
||||
resource_manager.wait_for_check_prerequisite.assert_not_called()
|
||||
resource_manager.should_delete.assert_not_called()
|
||||
resource_manager.delete.assert_not_called()
|
||||
resource_manager.disable.assert_not_called()
|
||||
resource_manager.assert_not_called()
|
||||
|
||||
def test_runner_delete_dry_run(self):
|
||||
resources = [mock.Mock(), mock.Mock()]
|
||||
resource_manager = mock.Mock(list=mock.Mock(return_value=resources))
|
||||
options = mock.Mock(dry_run=True)
|
||||
options = mock.Mock(dry_run=True, disable_only=False)
|
||||
exit = mock.Mock(is_set=mock.Mock(return_value=False))
|
||||
|
||||
main.runner(resource_manager, options, exit)
|
||||
|
@ -109,7 +142,7 @@ class TestFunctions(unittest.TestCase):
|
|||
def test_runner_resource(self):
|
||||
resources = [mock.Mock()]
|
||||
resource_manager = mock.Mock(list=mock.Mock(return_value=resources))
|
||||
options = mock.Mock(dry_run=False, resource=True)
|
||||
options = mock.Mock(dry_run=False, resource=True, disable_only=False)
|
||||
exit = mock.Mock(is_set=mock.Mock(return_value=False))
|
||||
main.runner(resource_manager, options, exit)
|
||||
resource_manager.wait_for_check_prerequisite.assert_not_called()
|
||||
|
|
|
@ -72,6 +72,77 @@ function assert_volume {
|
|||
fi
|
||||
}
|
||||
|
||||
########################
|
||||
# Disable asserts
|
||||
########################
|
||||
function test_neutron_disable {
|
||||
if [[ $(openstack port list -c Status -f value --device-owner compute:nova --project $demo_project_id | grep -ic 'active' ) -gt 0 ]]; then
|
||||
echo "Some of the ports is not disabled yet :)"
|
||||
exit 1
|
||||
fi
|
||||
if [[ $(openstack port list -c Status -f value --device-owner '' --project $demo_project_id | grep -ic 'active' ) -gt 0 ]]; then
|
||||
echo "Some of the ports is not disabled yet :)"
|
||||
exit 1
|
||||
fi
|
||||
if [[ $(openstack network list --no-share --long -c State -f value --project $demo_project_id | grep -ic 'UP' ) -gt 0 ]]; then
|
||||
echo "Some of the networks is not disabled yet :)"
|
||||
exit 1
|
||||
fi
|
||||
for router in $(openstack router list -c ID -f value --project $demo_project_id); do
|
||||
if [[ $(openstack router show $router -c admin_state_up -f value | grep -ic 'true' ) -gt 0 ]]; then
|
||||
echo "Some of the routers is not disabled yet :)"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
function test_cinder_disable {
|
||||
if [[ $(openstack volume list --long -c Properties -f value | grep -qvi 'readonly') ]]; then
|
||||
echo "Cinder volume is not disabled :)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function test_glance_disable {
|
||||
if [[ $(openstack image list --long -c Project -c Status -f value| grep $demo_project_id | grep -ic 'active' ) -gt 0 ]]; then
|
||||
echo "Some of the images is not disabled yet :)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function test_nova_disable {
|
||||
if [[ $(openstack server list -c Status -f value | grep -ic 'active' ) -gt 0 ]]; then
|
||||
echo "Some of the servers is not disabled yet :)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function test_loadbalancer_disable {
|
||||
for loadbalancer in $(openstack loadbalancer list -c id -f value --project $demo_project_id); do
|
||||
if [[ $(openstack loadbalancer show $loadbalancer -c admin_state_up -f value | grep -ic 'true' ) -gt 0 ]]; then
|
||||
echo "Some of the loadbalancers is not disabled yet :)"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
function test_swift_disable {
|
||||
for container in $(openstack container list -c Name -f value); do
|
||||
if [[ $(openstack container show $container -f json | grep -iq 'read[-_]acl:.*' ) ]]; then
|
||||
echo "Some of the containers is not disabled yet :)"
|
||||
exit 1
|
||||
fi
|
||||
if [[ $(openstack container show $container -f json | grep -iq 'write[-_]acl:.*' ) ]]; then
|
||||
echo "Some of the containers is not disabled yet :)"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
########################
|
||||
|
@ -113,9 +184,22 @@ done
|
|||
|
||||
echo "Done populating. Moving on to cleanup."
|
||||
|
||||
########################
|
||||
# Disable
|
||||
########################
|
||||
source $DEVSTACK_DIR/openrc admin admin
|
||||
demo_project_id=$(openstack project show demo -c id -f value | awk '{print $1}')
|
||||
source $DEVSTACK_DIR/openrc demo demo
|
||||
assert_compute && assert_network && assert_volume
|
||||
|
||||
tox -e run -- --os-cloud devstack --purge-own-project --verbose --disable-only # disable demo/demo
|
||||
test_neutron_disable && test_cinder_disable && test_glance_disable \
|
||||
&& test_nova_disable && test_loadbalancer_disable && test_swift_disable
|
||||
|
||||
########################
|
||||
### Cleanup
|
||||
########################
|
||||
source $DEVSTACK_DIR/openrc admin admin
|
||||
tox -e run -- --os-cloud devstack-admin --purge-own-project --verbose # purges admin/admin
|
||||
|
||||
source $DEVSTACK_DIR/openrc demo demo
|
||||
|
|
Loading…
Reference in New Issue