Add cleanup action
We can use fuel-devops for deletion of outdated environment. Usage: dos.py show-old 3d dos.py erase-old 3d where "3d" is time-to-live interval. All envs older than given interval will be erased. Last char of interval is multiplier, could be: - s: seconds - m: minutes - h: hours - d: days erase-old operation is interactive but it could be disabled via "--force-cleanup" arg. list-old command supports --timestamps arg. Note that devops uses UTC timestamps! Change-Id: Ic1a744996495296e22ae0fdef9752dba8790aac8
This commit is contained in:
parent
887368db3b
commit
3ac4e8fc7b
136
devops/shell.py
136
devops/shell.py
|
@ -19,8 +19,11 @@ import collections
|
|||
import os
|
||||
import sys
|
||||
|
||||
import datetime
|
||||
import tabulate
|
||||
|
||||
from six.moves import input
|
||||
|
||||
import devops
|
||||
from devops import client
|
||||
from devops import error
|
||||
|
@ -53,10 +56,53 @@ class Shell(object):
|
|||
print(tabulate.tabulate(columns, headers=headers,
|
||||
tablefmt="simple"))
|
||||
|
||||
def do_list(self):
|
||||
env_names = self.client.list_env_names()
|
||||
@staticmethod
|
||||
def query_yes_no(question, default=None):
|
||||
"""Ask a yes/no question via standard input and return the answer.
|
||||
|
||||
If invalid input is given, the user will be asked until
|
||||
they acutally give valid input.
|
||||
|
||||
Args:
|
||||
question(str):
|
||||
A question that is presented to the user.
|
||||
default(bool|None):
|
||||
The default value when enter is pressed with no value.
|
||||
When None, there is no default value and the query
|
||||
will loop.
|
||||
Returns:
|
||||
A bool indicating whether user has entered yes or no.
|
||||
|
||||
Side Effects:
|
||||
Blocks program execution until valid input(y/n) is given.
|
||||
"""
|
||||
yes_list = ["yes", "y"]
|
||||
no_list = ["no", "n"]
|
||||
|
||||
default_dict = { # default => prompt default string
|
||||
None: "[y/n]",
|
||||
True: "[Y/n]",
|
||||
False: "[y/N]",
|
||||
}
|
||||
default_str = default_dict[default]
|
||||
prompt_str = "{} {} ".format(question, default_str)
|
||||
|
||||
while True:
|
||||
choice = input(prompt_str).lower()
|
||||
|
||||
if not choice and default is not None:
|
||||
return default
|
||||
if choice in yes_list:
|
||||
return True
|
||||
if choice in no_list:
|
||||
return False
|
||||
|
||||
notification_str = "Please respond with 'y' or 'n'"
|
||||
print(notification_str)
|
||||
|
||||
def print_envs_table(self, env_names_list):
|
||||
columns = []
|
||||
for env_name in sorted(env_names):
|
||||
for env_name in sorted(env_names_list):
|
||||
env = self.client.get_env(env_name)
|
||||
column = collections.OrderedDict()
|
||||
column['NAME'] = env.name
|
||||
|
@ -72,6 +118,9 @@ class Shell(object):
|
|||
|
||||
self.print_table(headers='keys', columns=columns)
|
||||
|
||||
def do_list(self):
|
||||
self.print_envs_table(self.client.list_env_names())
|
||||
|
||||
def do_show(self):
|
||||
nodes = sorted(self.env.get_nodes(), key=lambda node: node.name)
|
||||
headers = ("VNC", "NODE-NAME", "GROUP-NAME")
|
||||
|
@ -131,6 +180,58 @@ class Shell(object):
|
|||
def do_erase(self):
|
||||
self.env.erase()
|
||||
|
||||
def get_lifetime_delta(self):
|
||||
data = self.params.env_lifetime
|
||||
multipliers = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}
|
||||
if data[-1] not in multipliers:
|
||||
raise ValueError(
|
||||
'Value should end with '
|
||||
'one of "{}", got "{}"'.format(
|
||||
" ".join(multipliers.keys()), data
|
||||
))
|
||||
num = int(data[:-1])
|
||||
mul = data[-1]
|
||||
return datetime.timedelta(seconds=num*multipliers[mul])
|
||||
|
||||
def get_old_environments(self):
|
||||
delta = self.get_lifetime_delta()
|
||||
# devops uses utc timestamps for BaseModel
|
||||
timestamp_now = datetime.datetime.utcnow()
|
||||
envs_to_erase = []
|
||||
for env_name in client.DevopsClient.list_env_names():
|
||||
env = client.DevopsClient.get_env(env_name)
|
||||
if (timestamp_now - env.created) > delta:
|
||||
envs_to_erase.append(env)
|
||||
return envs_to_erase
|
||||
|
||||
def do_erase_old(self):
|
||||
envs_to_erase = self.get_old_environments()
|
||||
|
||||
for env in envs_to_erase:
|
||||
print("Env '{}' will be erased!".format(env.name))
|
||||
|
||||
if envs_to_erase:
|
||||
if not self.params.force_cleanup:
|
||||
answer = self.query_yes_no(
|
||||
"The cleanup operation is destructive one, "
|
||||
"all environments listed above will be erased. "
|
||||
"DELETION CAN NOT BE UNDONE! Proceed? ",
|
||||
default=False)
|
||||
if not answer:
|
||||
print("Wise choice, aborting...")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("Nothing to erase, exiting...")
|
||||
sys.exit(0)
|
||||
|
||||
for env in envs_to_erase:
|
||||
print("Erasing '{}'...".format(env.name))
|
||||
env.erase()
|
||||
|
||||
def do_list_old(self):
|
||||
env_names = [env.name for env in self.get_old_environments()]
|
||||
self.print_envs_table(env_names)
|
||||
|
||||
def do_start(self):
|
||||
self.env.start()
|
||||
|
||||
|
@ -475,6 +576,22 @@ class Shell(object):
|
|||
'If set to 0, the disk will not be '
|
||||
'allocated',
|
||||
default=50, type=int)
|
||||
|
||||
force_cleanup_parser = argparse.ArgumentParser(add_help=False)
|
||||
force_cleanup_parser.add_argument(
|
||||
'--force-cleanup',
|
||||
dest='force_cleanup',
|
||||
action='store_const', const=True,
|
||||
help='Do not ask confirmation for cleanup action.',
|
||||
default=False)
|
||||
|
||||
env_lifetime = argparse.ArgumentParser(add_help=False)
|
||||
env_lifetime.add_argument(
|
||||
dest='env_lifetime',
|
||||
help='Erase environments older than given time interval. '
|
||||
'Example:"45m", "12h", "3d"',
|
||||
default="", type=str)
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Manage virtual environments. "
|
||||
"For additional help, use with -h/--help option")
|
||||
|
@ -485,6 +602,19 @@ class Shell(object):
|
|||
parents=[list_ips_parser, timestamps_parser],
|
||||
help="Show virtual environments",
|
||||
description="Show virtual environments on host")
|
||||
subparsers.add_parser('erase-old',
|
||||
parents=[force_cleanup_parser,
|
||||
env_lifetime],
|
||||
help="Cleanup old virtual environments",
|
||||
description="Cleanup virtual environments on "
|
||||
"host")
|
||||
subparsers.add_parser('list-old',
|
||||
parents=[env_lifetime, list_ips_parser,
|
||||
timestamps_parser],
|
||||
help="Show virtual environments older than given"
|
||||
" lifetime interval",
|
||||
description="Show old virtual "
|
||||
"environments on host")
|
||||
subparsers.add_parser('show', parents=[name_parser],
|
||||
help="Show VMs in environment",
|
||||
description="Show VMs in environment")
|
||||
|
|
Loading…
Reference in New Issue