246be3fe0010dd2d1110d64b41e9b228ad93bf31
[nfvbench.git] / nfvbench / cleanup.py
1 #!/usr/bin/env python
2 # Copyright 2017 Cisco Systems, Inc.  All rights reserved.
3 #
4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
5 #    not use this file except in compliance with the License. You may obtain
6 #    a copy of the License at
7 #
8 #         http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #    Unless required by applicable law or agreed to in writing, software
11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 #    License for the specific language governing permissions and limitations
14 #    under the License.
15 #
16
17 import sys
18 import time
19
20 from neutronclient.neutron import client as nclient
21 from novaclient.client import Client
22 from novaclient.exceptions import NotFound
23 from tabulate import tabulate
24
25 import credentials as credentials
26 from log import LOG
27
28 class ComputeCleaner(object):
29     """A cleaner for compute resources."""
30
31     def __init__(self, nova_client, instance_prefix):
32         self.nova_client = nova_client
33         LOG.info('Discovering instances %s...', instance_prefix)
34         all_servers = self.nova_client.servers.list()
35         self.servers = [server for server in all_servers
36                         if server.name.startswith(instance_prefix)]
37
38     def instance_exists(self, server):
39         try:
40             self.nova_client.servers.get(server.id)
41         except NotFound:
42             return False
43         return True
44
45     def get_resource_list(self):
46         return [["Instance", server.name, server.id] for server in self.servers]
47
48     def clean(self):
49         if self.servers:
50             for server in self.servers:
51                 try:
52                     LOG.info('Deleting instance %s...', server.name)
53                     self.nova_client.servers.delete(server.id)
54                 except Exception:
55                     LOG.exception("Instance %s deletion failed", server.name)
56             LOG.info('    Waiting for %d instances to be fully deleted...', len(self.servers))
57             retry_count = 5 + len(self.servers) * 2
58             while True:
59                 retry_count -= 1
60                 self.servers = [server for server in self.servers if self.instance_exists(server)]
61                 if not self.servers:
62                     break
63
64                 if retry_count:
65                     LOG.info('    %d yet to be deleted by Nova, retries left=%d...',
66                              len(self.servers), retry_count)
67                     time.sleep(2)
68                 else:
69                     LOG.warning('    instance deletion verification timed out: %d not removed',
70                                 len(self.servers))
71                     break
72
73
74 class NetworkCleaner(object):
75     """A cleaner for network resources."""
76
77     def __init__(self, neutron_client, network_names):
78         self.neutron_client = neutron_client
79         LOG.info('Discovering networks...')
80         all_networks = self.neutron_client.list_networks()['networks']
81         self.networks = []
82         for net in all_networks:
83             try:
84                 network_names.remove(net['name'])
85                 self.networks.append(net)
86             except ValueError:
87                 pass
88             if not network_names:
89                 break
90         net_ids = [net['id'] for net in self.networks]
91         if net_ids:
92             LOG.info('Discovering ports...')
93             all_ports = self.neutron_client.list_ports()['ports']
94             self.ports = [port for port in all_ports if port['network_id'] in net_ids]
95         else:
96             self.ports = []
97
98     def get_resource_list(self):
99         res_list = [["Network", net['name'], net['id']] for net in self.networks]
100         res_list.extend([["Port", port['name'], port['id']] for port in self.ports])
101         return res_list
102
103     def clean(self):
104         for port in self.ports:
105             LOG.info("Deleting port %s...", port['id'])
106             try:
107                 self.neutron_client.delete_port(port['id'])
108             except Exception:
109                 LOG.exception("Port deletion failed")
110
111         for net in self.networks:
112             LOG.info("Deleting network %s...", net['name'])
113             try:
114                 self.neutron_client.delete_network(net['id'])
115             except Exception:
116                 LOG.exception("Network deletion failed")
117
118 class FlavorCleaner(object):
119     """Cleaner for NFVbench flavor."""
120
121     def __init__(self, nova_client, name):
122         self.name = name
123         LOG.info('Discovering flavor %s...', name)
124         try:
125             self.flavor = nova_client.flavors.find(name=name)
126         except NotFound:
127             self.flavor = None
128
129     def get_resource_list(self):
130         if self.flavor:
131             return [['Flavor', self.name, self.flavor.id]]
132         return None
133
134     def clean(self):
135         if self.flavor:
136             LOG.info("Deleting flavor %s...", self.flavor.name)
137             try:
138                 self.flavor.delete()
139             except Exception:
140                 LOG.exception("Flavor deletion failed")
141
142 class Cleaner(object):
143     """Cleaner for all NFVbench resources."""
144
145     def __init__(self, config):
146         cred = credentials.Credentials(config.openrc_file, None, False)
147         session = cred.get_session()
148         self.neutron_client = nclient.Client('2.0', session=session)
149         self.nova_client = Client(2, session=session)
150         network_names = [inet['name'] for inet in config.internal_networks.values()]
151         self.cleaners = [ComputeCleaner(self.nova_client, config.loop_vm_name),
152                          FlavorCleaner(self.nova_client, config.flavor_type),
153                          NetworkCleaner(self.neutron_client, network_names)]
154
155     def show_resources(self):
156         """Show all NFVbench resources."""
157         table = [["Type", "Name", "UUID"]]
158         for cleaner in self.cleaners:
159             res_list = cleaner.get_resource_list()
160             if res_list:
161                 table.extend(res_list)
162         count = len(table) - 1
163         if count:
164             LOG.info('Discovered %d NFVbench resources:', count)
165             print tabulate(table, headers="firstrow", tablefmt="psql")
166         else:
167             LOG.info('No matching NFVbench resources found')
168         return count
169
170     def clean(self, prompt):
171         """Clean all resources."""
172         LOG.info("NFVbench will delete all resources shown...")
173         if prompt:
174             answer = raw_input("Are you sure? (y/n) ")
175             if answer.lower() != 'y':
176                 LOG.info("Exiting without deleting any resource")
177                 sys.exit(0)
178         for cleaner in self.cleaners:
179             cleaner.clean()