/usr/bin/bauble-admin is in bauble 0.9.7-2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | #!/usr/bin/python
#
# Copyright (c) 2005,2006,2007,2008 Brett Adams <brett@belizebotanic.org>
# This is free software, see GNU General Public License v2 for details.
"""
The bauble-admin script makes it easier to create and database and change
some of its properties.
"""
import sys
import os
from optparse import OptionParser
from getpass import getpass
import logging
from logging import info, warn, error
print '\n*** This script is considered ALPHA quality. You mileage may vary.\n'
usage = 'usage: %prog [command] [options] dbname'
parser = OptionParser(usage)
parser.add_option('-H', '--host', dest='hostname', metavar='HOST',
help='the host to connect to')
parser.add_option('-u', '--user', dest='user', metavar='USER',
help='the user name to use when connecting to the server')
parser.add_option('-P', '--port', dest='port', metavar='PORT',
help='the port on the server to connect to')
parser.add_option('-o', '--owner', dest='owner', metavar='OWNER',
help='the owner of the newly created database, if not ' \
'set then use the user name')
parser.add_option('-p', action='store_true', default=False, dest='password',
help='ask for a password')
parser.add_option('-d', '--dbtype', dest='dbtype', metavar='TYPE',
help='the database type')
parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
default=False, help='verbose output')
parser.add_option('-y', '--dryrun', dest='dryrun', action='store_true',
default=False, help="don't execute anything")
options, args = parser.parse_args()
commands = {}
logging.basicConfig(format='%(levelname)s: %(message)s')
#if options.verbose:
logging.getLogger().setLevel(logging.INFO)
def error_and_exit(msg, retval=1):
error(msg)
sys.exit(retval)
default_encoding = 'UTF8'
class Command(object):
"""
New commands should subclass the Command class.
"""
def __init__(self):
if self.__doc__ == Command.__doc__:
warn('No help set for %s' % self)
@classmethod
def run(self):
raise NotImplementedError
def execute(cursor, command, verbose=options.verbose):
if verbose:
logging.info(command)
if not options.dryrun:
cursor.execute(command)
return cursor
class CreateCommand(Command):
"""
The create command creates a database.
"""
name = 'create'
@classmethod
def run(cls):
if options.dbtype != 'postgres':
error_and_exit('Creating a database is only supported for '
'PostgreSQL database')
cls._run_postgres()
@classmethod
def _run_mysql(cls):
raise NotImplementedError
@classmethod
def _run_postgres(cls):
# ISOLATION_LEVEL_AUTOCOMMIT needed from create database
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
cursor = None
if not options.dryrun:
conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
cursor = conn.cursor()
# check if the database already exists
sql = "SELECT datname FROM pg_database WHERE datname='%s';" % dbname
execute(cursor, sql)
if not options.dryrun:
rows = cursor.fetchall()
if (dbname,) in rows:
print 'database %s already exists' % dbname
sys.exit(1)
# create the owner if the owner doesn't already exist
sql = "SELECT rolname FROM pg_roles WHERE rolname='%s';" % \
options.owner
execute(cursor, sql, verbose=False)
password = ''
if not options.dryrun:
if (options.owner,) in cursor.fetchall():
print 'user %s already exist' % options.owner
else:
password = getpass('Password for new database owner %s: ' % \
options.owner)
sql = "CREATE ROLE %s LOGIN PASSWORD '%s';" % \
(options.owner, password)
execute(cursor, sql)
# create the database and give owner permissions full permissions
options_dict = dict(dbname=dbname, owner=options.owner,
encoding=default_encoding)
sql = 'CREATE DATABASE %(dbname)s WITH OWNER="%(owner)s" ' \
'ENCODING=\'%(encoding)s\';' % options_dict
execute(cursor, sql)
sql = 'GRANT ALL ON DATABASE %(dbname)s TO "%(owner)s" ' \
'WITH GRANT OPTION;' % options_dict
execute(cursor, sql)
class GroupCommand(Command):
"""
The group command allows you to add, remove and change groups on a
database
With this command you can either create "admin" groups or regular
groups. For more fine-grained control then you must edit the database
manually.
"""
name = 'group'
@classmethod
def run(cls):
pass
def _run_postgres(cls):
pass
class UserCommand(Command):
"""
The user command allows you to add, remove and change the
permissions of a user on a database.
With this command you can either create "admin" users or regular users.
For more fine-grained control then you must edit the database manually.
"""
name = 'user'
@classmethod
def run(cls):
if options.dbtype != 'postgres':
error_and_exit('User properties can only be changed on a '
'postgres database.')
cls._run_postgres()
@classmethod
def _run_postgres(cls):
# TODO: get subcommands
pass
class DropCommand(Command):
"""
Remove a database from a server. BE CAREFUL.
"""
name = 'drop'
@classmethod
def _run_postgres(cls):
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
cursor = conn.cursor()
msg = '** WARNING: Dropping a database will completely remove the ' \
'database and all its data. Are you sure you want to drop the ' \
'"%s" database? ' % dbname
response = raw_input(msg)
if response not in ('Y', 'y'):
print 'Whew.'
return
args = []
for a in connect_args:
if a.startswith('dbname='):
args.append('dbname=postgres')
else:
args.append(a)
logging.info(args)
conn2 = dbapi.connect(' '.join(connect_args))
conn2.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
cursor2 = conn2.cursor()
#logging.info(connect_args)
sql = 'DROP DATABASE %s;' % dbname
execute(cursor2, sql)
conn2.close()
@classmethod
def run(cls):
if options.dbtype != 'postgres':
error_and_exit('Creating a database is only supported for '
'PostgreSQL database')
cls._run_postgres()
def register_command(command):
"""
Register a new command.
"""
commands[command.name] = command
register_command(CreateCommand)
register_command(UserCommand)
register_command(DropCommand)
if len(args) < 1:
parser.error('You must supply a command')
cmd = args[0]
if cmd not in commands:
parser.error('%s is an invalid command' % cmd)
try:
dbname = args[-1]
except:
parser.error('You must specify a database name')
def build_postgres_command():
pass
def build_mysql_command():
pass
dbapi = None
if options.dbtype == 'sqlite':
parser.error('It it not necessary to use this script on an SQLite '
'database')
elif options.dbtype == 'postgres':
dbapi = __import__('psycopg2')
elif options.dbtype == 'mysql':
dbapi = __import__('MySQLdb')
else:
parser.error('You must specify the database type with -d')
if not options.user:
options.user = os.environ['USER']
if not options.owner:
# options.owner = #os.environ['USER']
options.owner = options.user
print 'Setting owner as %s' % options.owner
# build connect() args and connect to the server
connect_args = ['dbname=postgres']
if options.hostname is not None:
connect_args.append('host=%s' % options.hostname)
if options.password:
password = getpass('Password for %s: ' % options.user)
connect_args.append('password=%s' % password)
if options.user:
connect_args.append('user=%s' % options.user)
if options.port:
connect_args.append('port=%s' % options.port)
#connect_args = ' '.join(connect_args)
if options.verbose:
logging.info('connect_args: %s' % ' '.join(connect_args))
conn = None
if not options.dryrun:
conn = dbapi.connect(' '.join(connect_args))
commands[cmd].run()
conn.close()
|