python-troveclient/troveclient/v1/shell.py

493 lines
16 KiB
Python

from __future__ import print_function
import argparse
import copy
import os
import sys
import time
from troveclient import exceptions
from troveclient import utils
def _poll_for_status(poll_fn, obj_id, action, final_ok_states,
poll_period=5, show_progress=True):
"""Block while an action is being performed, periodically printing
progress.
"""
def print_progress(progress):
if show_progress:
msg = ('\rInstance %(action)s... %(progress)s%% complete'
% dict(action=action, progress=progress))
else:
msg = '\rInstance %(action)s...' % dict(action=action)
sys.stdout.write(msg)
sys.stdout.flush()
print()
while True:
obj = poll_fn(obj_id)
status = obj.status.lower()
progress = getattr(obj, 'progress', None) or 0
if status in final_ok_states:
print_progress(100)
print("\nFinished")
break
elif status == "error":
print("\nError %(action)s instance" % {'action': action})
break
else:
print_progress(progress)
time.sleep(poll_period)
def _print_instance(instance):
# Get rid of those ugly links
if instance._info.get('links'):
del(instance._info['links'])
utils.print_dict(instance._info)
def _find_instance(cs, instance):
"""Get a instance by ID."""
return utils.find_resource(cs.instances, instance)
def _find_flavor(cs, flavor):
"""Get a flavor by ID."""
return utils.find_resource(cs.flavors, flavor)
def _find_backup(cs, backup):
"""Gets a backup by ID."""
return utils.find_resource(cs.backups, backup)
# Flavor related calls
@utils.service_type('database')
def do_list_flavors(cs, args):
"""Lists available flavors."""
flavors = cs.flavors.list()
utils.print_list(flavors, ['id', 'name', 'ram'])
@utils.arg('flavor', metavar='<flavor>', help='ID of the flavor.')
@utils.service_type('database')
def do_show_flavor(cs, args):
"""Show details of a flavor."""
flavor = _find_flavor(cs, args.flavor)
_print_instance(flavor)
# Instance related calls
@utils.service_type('database')
def do_list(cs, args):
"""List all the instances."""
instances = cs.instances.list()
for instance in instances:
setattr(instance, 'flavor_id', instance.flavor['id'])
if hasattr(instance, 'volume'):
setattr(instance, 'size', instance.volume['size'])
utils.print_list(instances, ['id', 'name', 'status', 'flavor_id', 'size'])
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.service_type('database')
def do_show(cs, args):
"""Show details of an instance."""
instance = _find_instance(cs, args.instance)
instance._info['flavor'] = instance.flavor['id']
if hasattr(instance, 'volume'):
instance._info['volume'] = instance.volume['size']
_print_instance(instance)
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.service_type('database')
def do_delete(cs, args):
"""Deletes an instance."""
cs.instances.delete(args.instance)
@utils.arg('name',
metavar='<name>',
type=str,
help='Name of the instance')
@utils.arg('--size',
metavar='<size>',
type=int,
default=None,
help='Size of the instance disk in GB')
@utils.arg('flavor_id',
metavar='<flavor_id>',
help='Flavor of the instance')
@utils.arg('--databases', metavar='<databases>',
help='Optional list of databases.',
nargs="+", default=[])
@utils.arg('--users', metavar='<users>',
help='Optional list of users in the form user:password.',
nargs="+", default=[])
@utils.arg('--backup',
metavar='<backup>',
default=None,
help='A backup UUID')
@utils.arg('--availability_zone',
metavar='<availability_zone>',
default=None,
help='The Zone hint to give to nova')
@utils.service_type('database')
def do_create(cs, args):
"""Add a new instance."""
volume = None
if args.size:
volume = {"size": args.size}
restore_point = None
if args.backup:
restore_point = {"backupRef": self.backup}
databases = [{'name': value} for value in args.databases]
users = [{'name': n, 'password': p} for (n, p) in
[z.split(':')[:2] for z in args.users]]
instance = cs.instances.create(args.name,
args.flavor_id,
volume=volume,
databases=databases,
users=users,
restorePoint=restore_point,
availability_zone=args.availability_zone)
instance._info['flavor'] = instance.flavor['id']
if hasattr(instance, 'volume'):
instance._info['volume'] = instance.volume['size']
del(instance._info['links'])
_print_instance(instance)
@utils.arg('instance',
metavar='<instance>',
type=str,
help='UUID of the instance')
@utils.arg('flavor_id',
metavar='<flavor_id>',
help='Flavor of the instance')
def resize_flavor(cs, args):
"""Resizes the flavor of an instance."""
cs.instances.resize_flavor(args.instance, args.flavor_id)
@utils.arg('instance',
metavar='<instance>',
type=str,
help='UUID of the instance')
@utils.arg('size',
metavar='<size>',
type=int,
default=None,
help='Size of the instance disk in GB')
def resize_volume(cs, args):
"""Resizes the volume size of an instance."""
cs.instances.resize_volume(args.instance, args.size)
@utils.arg('instance',
metavar='<instance>',
type=str,
help='UUID of the instance')
def restart(cs, args):
"""Restarts the instance."""
cs.instances.restart(args.instance)
# Backup related commands
@utils.arg('backup', metavar='<backup>', help='ID of the backup.')
@utils.service_type('database')
def do_show_backup(cs, args):
"""Show details of a backup."""
backups = _find_backup(args.backup)
_print_instance(backup)
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.service_type('database')
def do_list_instance_backups(cs, args):
"""List available backups for an instance."""
backups = cs.instances.backups(args.instance)
utils.print_list(backups, ['id', 'instance_id',
'name', 'description', 'status'])
@utils.service_type('database')
def do_list_backups(cs, args):
"""List available backups."""
backups = cs.backups.list()
utils.print_list(backups, ['id', 'instance_id',
'name', 'description', 'status'])
@utils.arg('backup', metavar='<backup>', help='ID of the backup.')
@utils.service_type('database')
def do_delete_backup(cs, args):
"""Deletes a backup."""
cs.backups.delete(args.backup)
@utils.arg('name', metavar='<name>', help='Name of the backup.')
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.arg('--description', metavar='<description>',
default=None,
help='An optional description for the backup.')
@utils.service_type('database')
def do_create_backup(cs, args):
"""Deletes a backup."""
backup = cs.backups.create(args.name, args.instance,
description=args.description)
_print_instance(backup)
# Database related actions
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.arg('name', metavar='<name>', help='Name of the backup.')
@utils.arg('--character_set', metavar='<character_set>',
default=None,
help='Optional character set for database')
@utils.arg('--collate', metavar='<collate>', default=None,
help='Optional collation type for database')
@utils.service_type('database')
def do_create_database(cs, args):
"""Creates a database on an instance."""
database_dict = {'name': args.name}
if args.collate:
database_dict['collate'] = args.collate
if args.character_set:
database_dict['character_set'] = args.character_set
cs.databases.create(args.instance,
[database_dict])
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.service_type('database')
def do_list_databases(cs, args):
"""Lists available databases on an instance."""
wrapper = cs.databases.list(args.instance)
databases = wrapper.items
while (wrapper.next):
wrapper = cs.databases.list(args.instance, marker=wrapper.next)
databases = wrapper.items
utils.print_list(databases, ['name'])
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.arg('database', metavar='<database>', help='Name of the database.')
@utils.service_type('database')
def do_delete_database(cs, args):
"""Deletes a database."""
cs.databases.delete(args.instance, args.database)
# User related actions
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user')
@utils.arg('password', metavar='<password>', help='Password of user')
@utils.arg('--host', metavar='<host>', default=None,
help='Optional host of user')
@utils.arg('--databases', metavar='<databases>',
help='Optional list of databases.',
nargs="+", default=[])
@utils.service_type('database')
def do_create_user(cs, args):
"""Creates a user."""
databases = [{'name': value} for value in args.databases]
user = {'name': args.name, 'password': args.password,
'databases': databases}
if args.host:
user['host'] = args.host
cs.users.create(args.instance, [user])
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.service_type('database')
def do_list_users(cs, args):
"""Lists the users for a instance."""
wrapper = cs.users.list(args.instance)
users = wrapper.items
while (wrapper.next):
wrapper = cs.users.list(args.instance, marker=wrapper.next)
users += wrapper.items
utils.print_list(users, ['name', 'host', 'databases'])
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user')
@utils.arg('--host', metavar='<host>', default=None,
help='Optional host of user')
@utils.service_type('database')
def do_delete_user(cs, args):
"""Deletes a user from the instance."""
cs.users.delete(args.instance, args.name, hostname=args.host)
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user')
@utils.arg('--host', metavar='<host>', default=None,
help='Optional host of user')
@utils.service_type('database')
# Quoting is not working now that we arent using httplib2
# anymore and instead are using requests
def do_get_user(cs, args):
"""Gets a user from the instance."""
user = cs.users.get(args.instance, args.name, hostname=args.host)
_print_instance(user)
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user')
@utils.arg('--host', metavar='<host>', default=None,
help='Optional host of user')
@utils.service_type('database')
# Quoting is not working now that we arent using httplib2
# anymore and instead are using requests
def do_get_user_access(cs, args):
"""Gets a users access from the instance."""
access = cs.users.list_access(args.instance, args.name, hostname=args.host)
utils.print_list(access, ['name'])
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user')
@utils.arg('--host', metavar='<host>', default=None,
help='Optional host of user')
@utils.arg('--new_name', metavar='<new_name>', default=None,
help='Optional new name of user')
@utils.arg('--new_password', metavar='<new_password>', default=None,
help='Optional new password of user')
@utils.arg('--new_host', metavar='<new_host>', default=None,
help='Optional new host of user')
@utils.service_type('database')
# Quoting is not working now that we arent using httplib2
# anymore and instead are using requests
def do_update_user_attributes(cs, args):
"""Updates a users attributes from the instance."""
new_attrs = {}
if args.new_name:
new_attrs['name'] = args.new_name
if args.new_password:
new_attrs['password'] = args.new_password
if args.new_host:
new_attrs['host'] = args.new_host
cs.users.update_attributes(args.instance, args.name,
newuserattr=new_attrs, hostname=args.host)
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user')
@utils.arg('--host', metavar='<host>', default=None,
help='Optional host of user')
@utils.arg('databases', metavar='<databases>',
help='List of databases.',
nargs="+", default=[])
@utils.service_type('database')
def do_grant_user_access(cs, args):
"""Grants access to a atabase(s) for a user."""
cs.users.grant(args.instance, args.name,
args.databases, hostname=args.host)
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user')
@utils.arg('database', metavar='<database>', help='A single database.')
@utils.arg('--host', metavar='<host>', default=None,
help='Optional host of user')
@utils.service_type('database')
def do_revoke_user_access(cs, args):
"""Revokes access to a database for a user."""
cs.users.revoke(args.instance, args.name,
args.database, hostname=args.host)
# Limits related commands
@utils.service_type('database')
def do_list_limits(cs, args):
"""Lists the limits for a tenant."""
limits = cs.limits.list()
# Pop the first one, its absolute limits
absolute = limits.pop(0)
_print_instance(absolute)
utils.print_list(limits, ['value', 'verb', 'remaining', 'unit'])
# Root related commands
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.service_type('database')
def do_enable_root(cs, args):
"""Enables root for a instance."""
root = cs.root.create(args.instance)
utils.print_dict({'name': root[0], 'password': root[1]})
@utils.arg('instance', metavar='<instance>', help='UUID of the instance.')
@utils.service_type('database')
def do_get_root(cs, args):
"""Gets root enabled status for a instance."""
root = cs.root.is_root_enabled(args.instance)
utils.print_dict({'is_root_enabled': root.rootEnabled})
# security group related functions
@utils.service_type('database')
def do_list_security_groups(cs, args):
"""Lists all security gropus."""
wrapper = cs.security_groups.list()
sec_grps = wrapper.items
while (wrapper.next):
wrapper = cs.security_groups.list()
sec_grps += wrapper.items
utils.print_list(sec_grps, ['id', 'name', 'rules', 'instance_id'])
@utils.arg('security_group', metavar='<security_group>',
help='ID of the security group.')
@utils.service_type('database')
def do_show_security_group(cs, args):
"""Shows details about a security group."""
sec_grp = cs.security_groups.get(args.security_group)
_print_instance(sec_grp)
@utils.arg('security_group', metavar='<security_group>',
help='Security group name')
@utils.arg('protocol', metavar='<protocol>', help='Protocol')
@utils.arg('from_port', metavar='<from_port>', help='from port')
@utils.arg('to_port', metavar='<to_port>', help='to port')
@utils.arg('cidr', metavar='<cidr>', help='CIDR address')
@utils.service_type('database')
def do_create_security_group_rule(cs, args):
"""Creates a security group rule."""
rule = cs.security_group_rules.create(args.security_group,
args.protocol,
args.from_port,
args.to_port,
args.cidr)
_print_instance(rule)
@utils.arg('security_group_rule', metavar='<security_group_rule>',
help='Security group rule')
@utils.service_type('database')
def do_delete_security_group_rule(cs, args):
"""Deletes a security group rule."""
cs.security_group_rules.delete(args.security_group_rule)