2.0 beta NFVBENCH-91 Allow multi-chaining with separate edge networks
[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 = 15 + len(self.servers) * 5
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 time-out: %d still not deleted',
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_name_prefixes):
78         self.neutron_client = neutron_client
79         LOG.info('Discovering networks...')
80         all_networks = self.neutron_client.list_networks()['networks']
81         self.networks = []
82         net_ids = []
83         for net in all_networks:
84             netname = net['name']
85             for prefix in network_name_prefixes:
86                 if netname.startswith(prefix):
87                     self.networks.append(net)
88                     net_ids.append(net['id'])
89                     break
90         if net_ids:
91             LOG.info('Discovering ports...')
92             all_ports = self.neutron_client.list_ports()['ports']
93             self.ports = [port for port in all_ports if port['network_id'] in net_ids]
94         else:
95             self.ports = []
96
97     def get_resource_list(self):
98         res_list = [["Network", net['name'], net['id']] for net in self.networks]
99         res_list.extend([["Port", port['name'], port['id']] for port in self.ports])
100         return res_list
101
102     def clean(self):
103         for port in self.ports:
104             LOG.info("Deleting port %s...", port['id'])
105             try:
106                 self.neutron_client.delete_port(port['id'])
107             except Exception:
108                 LOG.exception("Port deletion failed")
109
110         for net in self.networks:
111             LOG.info("Deleting network %s...", net['name'])
112             try:
113                 self.neutron_client.delete_network(net['id'])
114             except Exception:
115                 LOG.exception("Network deletion failed")
116
117 class FlavorCleaner(object):
118     """Cleaner for NFVbench flavor."""
119
120     def __init__(self, nova_client, name):
121         self.name = name
122         LOG.info('Discovering flavor %s...', name)
123         try:
124             self.flavor = nova_client.flavors.find(name=name)
125         except NotFound:
126             self.flavor = None
127
128     def get_resource_list(self):
129         if self.flavor:
130             return [['Flavor', self.name, self.flavor.id]]
131         return None
132
133     def clean(self):
134         if self.flavor:
135             LOG.info("Deleting flavor %s...", self.flavor.name)
136             try:
137                 self.flavor.delete()
138             except Exception:
139                 LOG.exception("Flavor deletion failed")
140
141 class Cleaner(object):
142     """Cleaner for all NFVbench resources."""
143
144     def __init__(self, config):
145         cred = credentials.Credentials(config.openrc_file, None, False)
146         session = cred.get_session()
147         self.neutron_client = nclient.Client('2.0', session=session)
148         self.nova_client = Client(2, session=session)
149         network_names = [inet['name'] for inet in config.internal_networks.values()]
150         self.cleaners = [ComputeCleaner(self.nova_client, config.loop_vm_name),
151                          FlavorCleaner(self.nova_client, config.flavor_type),
152                          NetworkCleaner(self.neutron_client, network_names)]
153
154     def show_resources(self):
155         """Show all NFVbench resources."""
156         table = [["Type", "Name", "UUID"]]
157         for cleaner in self.cleaners:
158             res_list = cleaner.get_resource_list()
159             if res_list:
160                 table.extend(res_list)
161         count = len(table) - 1
162         if count:
163             LOG.info('Discovered %d NFVbench resources:\n%s', count,
164                      tabulate(table, headers="firstrow", tablefmt="psql"))
165         else:
166             LOG.info('No matching NFVbench resources found')
167         return count
168
169     def clean(self, prompt):
170         """Clean all resources."""
171         LOG.info("NFVbench will delete all resources shown...")
172         if prompt:
173             answer = raw_input("Are you sure? (y/n) ")
174             if answer.lower() != 'y':
175                 LOG.info("Exiting without deleting any resource")
176                 sys.exit(0)
177         for cleaner in self.cleaners:
178             cleaner.clean()