510 lines
16 KiB
Python
510 lines
16 KiB
Python
#!/usr/bin/env python
|
|
|
|
# Copyright 2011 OpenStack Foundation
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
"""
|
|
Trove Command line tool
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
|
|
from troveclient.compat import common
|
|
|
|
# If ../trove/__init__.py exists, add ../ to Python search path, so that
|
|
# it will override what happens to be installed in /usr/(local/)lib/python...
|
|
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
|
os.pardir,
|
|
os.pardir))
|
|
if os.path.exists(os.path.join(possible_topdir, 'troveclient',
|
|
'__init__.py')):
|
|
sys.path.insert(0, possible_topdir)
|
|
|
|
|
|
class InstanceCommands(common.AuthedCommandsBase):
|
|
"""Commands to perform various instance operations and actions."""
|
|
|
|
params = [
|
|
'flavor',
|
|
'id',
|
|
'limit',
|
|
'marker',
|
|
'name',
|
|
'size',
|
|
'backup',
|
|
'availability_zone',
|
|
'configuration_id',
|
|
]
|
|
|
|
def _get_configuration_ref(self):
|
|
configuration_ref = None
|
|
if self.configuration_id is not None:
|
|
if self.configuration_id == "":
|
|
configuration_ref = self.configuration_id
|
|
else:
|
|
configuration_ref = "/".join(
|
|
[
|
|
self.dbaas.client.service_url,
|
|
self.configuration_id,
|
|
]
|
|
)
|
|
return configuration_ref
|
|
|
|
def create(self):
|
|
"""Create a new instance."""
|
|
self._require('name', 'flavor')
|
|
volume = None
|
|
if self.size:
|
|
volume = {"size": self.size}
|
|
restorePoint = None
|
|
if self.backup:
|
|
restorePoint = {"backupRef": self.backup}
|
|
self._pretty_print(self.dbaas.instances.create, self.name,
|
|
self.flavor, volume, restorePoint=restorePoint,
|
|
availability_zone=self.availability_zone,
|
|
configuration=self._get_configuration_ref())
|
|
|
|
# TODO(pdmars): is this actually what this should be named?
|
|
def modify(self):
|
|
"""Modify an instance."""
|
|
self._require('id')
|
|
self._pretty_print(self.dbaas.instances.modify, self.id,
|
|
configuration=self._get_configuration_ref())
|
|
|
|
def delete(self):
|
|
"""Delete the specified instance."""
|
|
self._require('id')
|
|
print(self.dbaas.instances.delete(self.id))
|
|
|
|
def get(self):
|
|
"""Get details for the specified instance."""
|
|
self._require('id')
|
|
self._pretty_print(self.dbaas.instances.get, self.id)
|
|
|
|
def backups(self):
|
|
"""Get a list of backups for the specified instance."""
|
|
self._require('id')
|
|
self._pretty_list(self.dbaas.instances.backups, self.id)
|
|
|
|
def list(self):
|
|
"""List all instances for account."""
|
|
# limit and marker are not required.
|
|
limit = self.limit or None
|
|
if limit:
|
|
limit = int(limit, 10)
|
|
self._pretty_paged(self.dbaas.instances.list)
|
|
|
|
def resize_volume(self):
|
|
"""Resize an instance volume."""
|
|
self._require('id', 'size')
|
|
self._pretty_print(self.dbaas.instances.resize_volume, self.id,
|
|
self.size)
|
|
|
|
def resize_instance(self):
|
|
"""Resize an instance flavor"""
|
|
self._require('id', 'flavor')
|
|
self._pretty_print(self.dbaas.instances.resize_instance, self.id,
|
|
self.flavor)
|
|
|
|
def restart(self):
|
|
"""Restart the database."""
|
|
self._require('id')
|
|
self._pretty_print(self.dbaas.instances.restart, self.id)
|
|
|
|
def configuration(self):
|
|
"""Get configuration for the specified instance."""
|
|
self._require('id')
|
|
self._pretty_print(self.dbaas.instances.configuration, self.id)
|
|
|
|
|
|
class FlavorsCommands(common.AuthedCommandsBase):
|
|
"""Command for listing Flavors."""
|
|
|
|
params = []
|
|
|
|
def list(self):
|
|
"""List the available flavors."""
|
|
self._pretty_list(self.dbaas.flavors.list)
|
|
|
|
|
|
class DatabaseCommands(common.AuthedCommandsBase):
|
|
"""Database CRUD operations on an instance."""
|
|
|
|
params = [
|
|
'name',
|
|
'id',
|
|
'limit',
|
|
'marker',
|
|
]
|
|
|
|
def create(self):
|
|
"""Create a database."""
|
|
self._require('id', 'name')
|
|
databases = [{'name': self.name}]
|
|
print(self.dbaas.databases.create(self.id, databases))
|
|
|
|
def delete(self):
|
|
"""Delete a database."""
|
|
self._require('id', 'name')
|
|
print(self.dbaas.databases.delete(self.id, self.name))
|
|
|
|
def list(self):
|
|
"""List the databases."""
|
|
self._require('id')
|
|
self._pretty_paged(self.dbaas.databases.list, self.id)
|
|
|
|
|
|
class UserCommands(common.AuthedCommandsBase):
|
|
"""User CRUD operations on an instance."""
|
|
params = [
|
|
'id',
|
|
'database',
|
|
'databases',
|
|
'hostname',
|
|
'name',
|
|
'password',
|
|
'new_name',
|
|
'new_host',
|
|
'new_password',
|
|
]
|
|
|
|
def create(self):
|
|
"""Create a user in instance, with access to one or more databases."""
|
|
self._require('id', 'name', 'password', 'databases')
|
|
self._make_list('databases')
|
|
databases = [{'name': dbname} for dbname in self.databases]
|
|
users = [{'name': self.name, 'password': self.password,
|
|
'databases': databases}]
|
|
if self.hostname:
|
|
users[0]['host'] = self.hostname
|
|
self.dbaas.users.create(self.id, users)
|
|
|
|
def delete(self):
|
|
"""Delete the specified user"""
|
|
self._require('id', 'name')
|
|
self.dbaas.users.delete(self.id, self.name, self.hostname)
|
|
|
|
def get(self):
|
|
"""Get a single user."""
|
|
self._require('id', 'name')
|
|
self._pretty_print(self.dbaas.users.get, self.id,
|
|
self.name, self.hostname)
|
|
|
|
def update_attributes(self):
|
|
"""Update attributes of a single user."""
|
|
self._require('id', 'name')
|
|
self._require_at_least_one_of('new_name', 'new_host', 'new_password')
|
|
user_new = {}
|
|
if self.new_name:
|
|
user_new['name'] = self.new_name
|
|
if self.new_host:
|
|
user_new['host'] = self.new_host
|
|
if self.new_password:
|
|
user_new['password'] = self.new_password
|
|
self.dbaas.users.update_attributes(self.id, self.name, user_new,
|
|
self.hostname)
|
|
|
|
def list(self):
|
|
"""List all the users for an instance."""
|
|
self._require('id')
|
|
self._pretty_paged(self.dbaas.users.list, self.id)
|
|
|
|
def access(self):
|
|
"""Show all databases the user has access to."""
|
|
self._require('id', 'name')
|
|
self._pretty_list(self.dbaas.users.list_access, self.id,
|
|
self.name, self.hostname)
|
|
|
|
def grant(self):
|
|
"""Allow an existing user permissions to access one or more
|
|
databases.
|
|
"""
|
|
self._require('id', 'name', 'databases')
|
|
self._make_list('databases')
|
|
self.dbaas.users.grant(self.id, self.name, self.databases,
|
|
self.hostname)
|
|
|
|
def revoke(self):
|
|
"""Revoke from an existing user access permissions to a database."""
|
|
self._require('id', 'name', 'database')
|
|
self.dbaas.users.revoke(self.id, self.name, self.database,
|
|
self.hostname)
|
|
|
|
def change_password(self):
|
|
"""Change the password of a single user."""
|
|
self._require('id', 'name', 'password')
|
|
users = [{'name': self.name,
|
|
'host': self.hostname,
|
|
'password': self.password}]
|
|
self.dbaas.users.change_passwords(self.id, users)
|
|
|
|
|
|
class RootCommands(common.AuthedCommandsBase):
|
|
"""Root user related operations on an instance."""
|
|
|
|
params = [
|
|
'id',
|
|
]
|
|
|
|
def create(self):
|
|
"""Enable the instance's root user."""
|
|
self._require('id')
|
|
try:
|
|
user, password = self.dbaas.root.create(self.id)
|
|
print("User:\t\t%s\nPassword:\t%s" % (user, password))
|
|
except Exception:
|
|
print(sys.exc_info()[1])
|
|
|
|
def delete(self):
|
|
"""Disable the instance's root user."""
|
|
self._require('id')
|
|
print(self.dbaas.root.delete(self.id))
|
|
|
|
def enabled(self):
|
|
"""Check the instance for root access."""
|
|
self._require('id')
|
|
self._pretty_print(self.dbaas.root.is_root_enabled, self.id)
|
|
|
|
|
|
class VersionCommands(common.AuthedCommandsBase):
|
|
"""List available versions."""
|
|
|
|
params = [
|
|
'url',
|
|
]
|
|
|
|
def list(self):
|
|
"""List all the supported versions."""
|
|
self._require('url')
|
|
self._pretty_list(self.dbaas.versions.index, self.url)
|
|
|
|
|
|
class LimitsCommands(common.AuthedCommandsBase):
|
|
"""Show the rate limits and absolute limits."""
|
|
|
|
def list(self):
|
|
"""List the rate limits and absolute limits."""
|
|
self._pretty_list(self.dbaas.limits.list)
|
|
|
|
|
|
class BackupsCommands(common.AuthedCommandsBase):
|
|
"""Command to manage and show backups."""
|
|
params = ['name', 'instance', 'description']
|
|
|
|
def get(self):
|
|
"""Get details for the specified backup."""
|
|
self._require('id')
|
|
self._pretty_print(self.dbaas.backups.get, self.id)
|
|
|
|
def list(self):
|
|
"""List backups."""
|
|
self._pretty_list(self.dbaas.backups.list)
|
|
|
|
def create(self):
|
|
"""Create a new backup."""
|
|
self._require('name', 'instance')
|
|
self._pretty_print(self.dbaas.backups.create, self.name,
|
|
self.instance, self.description)
|
|
|
|
def delete(self):
|
|
"""Delete a backup."""
|
|
self._require('id')
|
|
self._pretty_print(self.dbaas.backups.delete, self.id)
|
|
|
|
|
|
class DatastoreConfigurationParameters(common.AuthedCommandsBase):
|
|
"""Command to show configuration parameters for a datastore."""
|
|
params = ['datastore', 'parameter']
|
|
|
|
def parameters(self):
|
|
"""List parameters that can be set."""
|
|
self._require('datastore')
|
|
self._pretty_print(self.dbaas.configuration_parameters.parameters,
|
|
self.datastore)
|
|
|
|
def get_parameter(self):
|
|
"""List parameters that can be set."""
|
|
self._require('datastore', 'parameter')
|
|
self._pretty_print(self.dbaas.configuration_parameters.get_parameter,
|
|
self.datastore, self.parameter)
|
|
|
|
|
|
class ConfigurationsCommands(common.AuthedCommandsBase):
|
|
"""Command to manage and show configurations."""
|
|
params = ['name', 'instances', 'values', 'description', 'parameter']
|
|
|
|
def get(self):
|
|
"""Get details for the specified configuration."""
|
|
self._require('id')
|
|
self._pretty_print(self.dbaas.configurations.get, self.id)
|
|
|
|
def list_instances(self):
|
|
"""Get details for the specified configuration."""
|
|
self._require('id')
|
|
self._pretty_list(self.dbaas.configurations.instances, self.id)
|
|
|
|
def list(self):
|
|
"""List configurations."""
|
|
self._pretty_list(self.dbaas.configurations.list)
|
|
|
|
def create(self):
|
|
"""Create a new configuration."""
|
|
self._require('name', 'values')
|
|
self._pretty_print(self.dbaas.configurations.create, self.name,
|
|
self.values, self.description)
|
|
|
|
def update(self):
|
|
"""Update an existing configuration."""
|
|
self._require('id', 'values')
|
|
self._pretty_print(self.dbaas.configurations.update, self.id,
|
|
self.values, self.name, self.description)
|
|
|
|
def edit(self):
|
|
"""Edit an existing configuration values."""
|
|
self._require('id', 'values')
|
|
self._pretty_print(self.dbaas.configurations.edit, self.id,
|
|
self.values)
|
|
|
|
def delete(self):
|
|
"""Delete a configuration."""
|
|
self._require('id')
|
|
self._pretty_print(self.dbaas.configurations.delete, self.id)
|
|
|
|
|
|
class SecurityGroupCommands(common.AuthedCommandsBase):
|
|
"""Commands to list and show Security Groups For an Instance and
|
|
create and delete security group rules for them.
|
|
"""
|
|
params = [
|
|
'id',
|
|
'secgroup_id',
|
|
'protocol',
|
|
'from_port',
|
|
'to_port',
|
|
'cidr'
|
|
]
|
|
|
|
def get(self):
|
|
"""Get a security group associated with an instance."""
|
|
self._require('id')
|
|
self._pretty_print(self.dbaas.security_groups.get, self.id)
|
|
|
|
def list(self):
|
|
"""List all the Security Groups and the rules."""
|
|
self._pretty_paged(self.dbaas.security_groups.list)
|
|
|
|
def add_rule(self):
|
|
"""Add a security group rule."""
|
|
self._require('secgroup_id', 'protocol',
|
|
'from_port', 'to_port', 'cidr')
|
|
self.dbaas.security_group_rules.create(self.secgroup_id, self.protocol,
|
|
self.from_port, self.to_port,
|
|
self.cidr)
|
|
|
|
def delete_rule(self):
|
|
"""Delete a security group rule."""
|
|
self._require('id')
|
|
self.dbaas.security_group_rules.delete(self.id)
|
|
|
|
|
|
class MetadataCommands(common.AuthedCommandsBase):
|
|
"""Commands to create/update/replace/delete/show metadata for an instance
|
|
"""
|
|
params = [
|
|
'instance_id',
|
|
'metadata'
|
|
]
|
|
|
|
def show(self):
|
|
"""Show instance metadata."""
|
|
self._require('instance_id')
|
|
self._pretty_print(self.dbaas.metadata.show(self.instance_id))
|
|
|
|
|
|
COMMANDS = {
|
|
'auth': common.Auth,
|
|
'instance': InstanceCommands,
|
|
'flavor': FlavorsCommands,
|
|
'database': DatabaseCommands,
|
|
'limit': LimitsCommands,
|
|
'backup': BackupsCommands,
|
|
'configuration': ConfigurationsCommands,
|
|
'user': UserCommands,
|
|
'root': RootCommands,
|
|
'version': VersionCommands,
|
|
'secgroup': SecurityGroupCommands,
|
|
'metadata': MetadataCommands,
|
|
}
|
|
|
|
|
|
def main():
|
|
# Parse arguments
|
|
load_file = True
|
|
for index, arg in enumerate(sys.argv):
|
|
if (arg == "auth" and len(sys.argv) > (index + 1) and
|
|
sys.argv[index + 1] == "login"):
|
|
load_file = False
|
|
|
|
oparser = common.CliOptions.create_optparser(load_file)
|
|
for k, v in COMMANDS.items():
|
|
v._prepare_parser(oparser)
|
|
(options, args) = oparser.parse_args()
|
|
|
|
if not args:
|
|
common.print_commands(COMMANDS)
|
|
|
|
if options.verbose:
|
|
os.environ['RDC_PP'] = "True"
|
|
os.environ['REDDWARFCLIENT_DEBUG'] = "True"
|
|
|
|
# Pop the command and check if it's in the known commands
|
|
cmd = args.pop(0)
|
|
if cmd in COMMANDS:
|
|
fn = COMMANDS.get(cmd)
|
|
command_object = None
|
|
try:
|
|
command_object = fn(oparser)
|
|
except Exception as ex:
|
|
if options.debug:
|
|
raise
|
|
print(ex)
|
|
|
|
# Get a list of supported actions for the command
|
|
actions = common.methods_of(command_object)
|
|
|
|
if len(args) < 1:
|
|
common.print_actions(cmd, actions)
|
|
|
|
# Check for a valid action and perform that action
|
|
action = args.pop(0)
|
|
if action in actions:
|
|
if not options.debug:
|
|
try:
|
|
getattr(command_object, action)()
|
|
except Exception as ex:
|
|
if options.debug:
|
|
raise
|
|
print(ex)
|
|
else:
|
|
getattr(command_object, action)()
|
|
else:
|
|
common.print_actions(cmd, actions)
|
|
else:
|
|
common.print_commands(COMMANDS)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|