Browse Source

ecn-robots: First commit

master
Nagy Karoly Gabriel 15 years ago
commit
5fac8bf996
2 changed files with 455 additions and 0 deletions
  1. +139
    -0
      pgdb.py
  2. +316
    -0
      vserver.py

+ 139
- 0
pgdb.py

@ -0,0 +1,139 @@
r'''Python interface to PostgreSQL for managing database nodes.
'''
from subprocess import Popen, PIPE
class Db(object):
def __init__(self,name):
self._name = name
def _run(self, command,args=[]):
execfn = [command] + list(args)
try:
p = Popen(execfn, stdout=PIPE, stderr=PIPE)
return p.communicate()
except Exception,e:
print str(e)
return -1
def _runsql(self, sql, db='postgres'):
given_sql = sql
out,error = self._run('/usr/bin/psql', ['-Aqt','-U','postgres','-d', db, '-c', given_sql])
return out.strip()
def _get_owner(self):
sql = "SELECT pg_get_userbyid(datdba) FROM pg_database WHERE datname ='"+self._name+"';"
own = self._runsql(sql)
return own
def _set_owner(self, owner):
sql = "ALTER DATABASE "+self._name+" OWNER TO "+owner+";"
own = self._runsql(sql)
return own
owner = property(_get_owner, _set_owner)
@property
def OID(self):
sql = "SELECT oid FROM pg_database WHERE datname = '"+self._name+"';"
oid = self._runsql(sql)
return oid
@property
def info(self):
information = {'size':'', 'encoding':'', 'collation':'','ctype':''}
information['size'] = self._runsql("SELECT pg_size_pretty(pg_database_size('"+self._name+"'));").strip()
information['encoding'], information['collation'], \
information['ctype'] = self._runsql("""SELECT pg_encoding_to_char(encoding),
datcollate, datctype FROM pg_database WHERE datname='"""+self._name+"';").strip().split('|')
return information
@property
def connections(self):
sql = "SELECT numbackends from pg_stat_database WHERE datname = '"+self._name+"';"
cncs = self._runsql(sql)
return cncs
def user_exists(self, user):
sql = "SELECT rolname FROM pg_authid WHERE rolname = '"+user+"';"
u = self._runsql(sql).strip()
if (u == ""):
return False
return True
def db_exists(self, xdb):
sql = "SELECT datname FROM pg_database WHERE datname = '"+xdb+"';"
d = self._runsql(sql).strip()
if (d == ""):
return False
return True
def delete(self):
if self.db_exists(self._name) == True:
sql = "DROP DATABASE "+self._name+";"
drop = self._runsql(sql)
return drop
return "Failed"
def create(self, own, coll, ctyp, enc=u'UTF8'):
if self.db_exists(self._name) == False:
sql = "CREATE DATABASE "+self._name+" WITH OWNER = "+own+" ENCODING = '"+enc+"' LC_COLLATE = '"+coll+"' LC_CTYPE = '"+ctyp+"';"
create = self._runsql(sql)
return create
return "Failed"
def dump(self, path, method):
dump = Popen(['/usr/bin/pg_dump', '-U','postgres','-F'+ method, self._name], stdout=PIPE)
fl = open(path,"wb")
gz = Popen(['gzip'], stdin = dump.stdout, stdout = fl)
fl.close
return "Finished dumping "+self._name
def rename(self,old, new):
if self.db_exists(new) == True or self.db_exists(old) == False:
return "Cannot"
sql = "ALTER DATABASE "+old+" RENAME TO "+new+";"
rename = self._runsql(sql)
return rename
def copy():
pass
def dblist(self):
sql = "SELECT datname FROM pg_database WHERE datname NOT IN ('template0', 'template1', 'postgres');"
dblist = self._runsql(sql)
return dblist
def usrlist(self):
sql = "SELECT rolname FROM pg_authid WHERE rolcanlogin=true;"
usrlist = self._runsql(sql)
return usrlist
def _test():
#test = Db(u'postgres')
#print test.info['encoding'], test.info['collation'], test.info['ctype']
#print test.owner
#print test.connections
#print "User aaa is ",test.user_exists("aaa")
#print "User postgres is ",test.user_exists("postgres")
#print "database xxxaaa is ", test.db_exists("xxxaaa")
#print "database postgres is ", test.db_exists("postgres")
#print test.dblist()
#test2 = Db(u'aaa')
#print test2.create(u'postgres', u'en_US.UTF-8', u'en_US.UTF-8')
#print test2.dblist()
#test2.rename(u'aaa',u'bbb')
#print test2.dblist()
#print test2.usrlist()
#print test2.owner
#test2.owner = u'karasz'
#print test2.owner
test = Db(u'aaa')
test.create(u'postgres', u'en_US.UTF-8', u'en_US.UTF-8')
print test.dump('/tmp/aaa.gz',u'p')
#test.delete()
if __name__ == '__main__':
_test()

+ 316
- 0
vserver.py

@ -0,0 +1,316 @@
r'''Python interface to Linux-VServer for managing hosting systems.
'''
__version__ = '0.2'
__author__ = 'Volker Grabsch'
__author_email__ = 'vog@notjusthosting.com'
__url__ = 'http://www.profv.de/python-vserver/'
__classifiers__ = '''
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
Intended Audience :: System Administrators
License :: OSI Approved :: MIT License
Operating System :: POSIX :: Linux
Programming Language :: Python
Topic :: Software Development :: Libraries :: Python Modules
Topic :: System :: Installation/Setup
Topic :: System :: Systems Administration
Topic :: Utilities
'''
__license__ = '''
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject
to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
'''
import subprocess
import os
import urllib2
import re
import math
class Error(RuntimeError):
def __init__(self, message_format, *args):
self._message = message_format % tuple(args)
def __str__(self):
return self._message.encode('UTF-8')
class System(object):
def __init__(self):
pass
def read_uri(self, uri):
f = urllib2.urlopen(uri)
try:
return f.read().decode('UTF-8')
finally:
f.close()
def read_binary(self, path):
if path[0] != u'/':
raise Error(u'Not an absolute path: %s', path)
f = file(path.encode('UTF-8'), 'r')
try:
return f.read()
finally:
f.close()
def write_binary(self, path, mode, binary):
if path[0] != u'/':
raise Error(u'Not an absolute path: %s', path)
try:
current_mode = os.stat(path.encode('UTF-8')).st_mode & 07777
if current_mode != mode:
raise Error(u'File already exists with different mode: %s\n'
u'\n'
u'Current mode: %04o\n'
u'Expected mode: %04o',
path, current_mode, mode)
except OSError, e:
pass
fd = os.open(path.encode('UTF-8'), os.O_CREAT | os.O_WRONLY | os.O_TRUNC, mode)
f = os.fdopen(fd, 'w')
try:
f.write(binary)
finally:
f.close()
# set mode again, because os.open() never sets suid/sgid/sticky bits
os.chmod(path.encode('UTF-8'), mode)
def run(self, command, input=None, allowed_returncodes=None):
if isinstance(command, basestring):
raise Error(u'The command should be given as list, not string: %r',
command)
if input is None:
stdin = file(os.devnull, 'r')
else:
stdin = subprocess.PIPE
input = input.encode('UTF-8')
try:
process = subprocess.Popen(
[arg.encode('UTF-8') for arg in command],
bufsize=0,
stdin=stdin,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=True,
shell=False,
cwd=None,
env={u'PATH': os.getenv(u'PATH')},
universal_newlines=False,
)
except OSError, e:
raise Error(u'Command %r: %s', command, e)
output, error = process.communicate(input)
output = output.decode('UTF-8')
error = error.decode('UTF-8')
returncode = process.returncode
if allowed_returncodes is None:
allowed_returncodes = [0]
if returncode not in allowed_returncodes:
raise Error(u'Command failed: %r\n\nReturn code: %i\n\nOutput:\n%s\n\nError:\n%s',
command, returncode, output.strip('\n'), error.strip('\n'))
return returncode, output.decode('UTF-8')
def convert_human(self, secs):
mins, secs = divmod(secs, 60)
hours, mins = divmod(mins, 60)
days, hours = divmod(hours, 24)
interval = '%d days %d hours %d minutes %d seconds' % (days, hours, mins, secs)
return interval
def get_line_value(self, file, tag):
if os.path.isfile(file):
with open(file) as f:
val = f.readline()
while val:
if val.startswith(tag):
val=val.replace(tag,'')
value = val.strip()
val = f.readline()
return value
return 'None'
class Host(object):
def __init__(self):
self.p = System()
def vserver_list(self):
list = os.listdir(u'/etc/vservers/')
list.remove(u'.defaults')
list.remove(u'.distributions')
list.remove(u'lost+found')
return list
@property
def info(self):
information= {'kernel':'', 'uptime':'' }
returncode, kernel = self.p.run([u'uname', u'-r'])
information['kernel'] = kernel.strip()
secs = math.ceil(float(self.p.read_binary(u'/proc/uptime').split()[1]))
information['uptime'] = self.p.convert_human(secs)
return information
class VServer(object):
def __init__(self, name):
self.p = System()
self._name = name
self._dirs = {}
def read_uri(self, uri):
return self.p.read_uri(uri)
def _one_line(self, text):
if text == u'':
raise Error(u'Empty line.')
if u'\n' in text[:-1]:
raise Error(u'Multiple lines where a single line was expected:\n%s', text.strip(u'\n'))
if text[-1] != u'\n':
raise Error(u'Incomplete line: %s', text)
return text[:-1]
def _path(self, path_type, path):
if path[0] != u'/':
raise Error(u'Not an absolute path: %s', path)
if not self._dirs.has_key(path_type):
returncode, output = self.p.run([u'vserver-info', self._name, path_type])
self._dirs[path_type] = self._one_line(output)
return self._dirs[path_type] + path
def _read_cfg(self, path):
return self.p.read_binary(self._path(u'CFGDIR', path)).decode('UTF-8')
def _write_cfg(self, path, mode, content):
self.p.write_binary(self._path(u'CFGDIR', path), mode, content.encode('UTF-8'))
def read_binary(self, path):
return self.p.read_binary(self._path(u'VDIR', path))
def write_binary(self, path, mode, binary):
self.p.write_binary(self._path(u'VDIR', path), mode, binary)
def read(self, path):
return self.read_binary(path).decode('UTF-8')
def write(self, path, mode, content):
self.write_binary(path, mode, content.encode('UTF-8'))
def read_one_line(self, path):
return self._one_line(self.read(path))
def write_one_line(self, path, mode, line):
if u'\n' in line:
raise Error(u'Invalid line break in: %r', line)
self.write(path, mode, u'%s\n' % (line,))
def run(self, command, input=None, allowed_returncodes=None):
return self.p.run([u'vserver', self._name, u'exec'] + command,
input, allowed_returncodes)
def _get_running(self):
returncode, output = self.p.run([u'vserver', self._name, u'running'],
allowed_returncodes=[0, 1])
return (returncode == 0)
def _set_running(self, running):
if running:
self.p.run([u'vserver', self._name, u'start'])
else:
self.p.run([u'vserver', self._name, u'stop'])
running = property(_get_running, _set_running)
@property
def context(self):
"""Get the context of speciffied vserver."""
with open(u'/etc/vservers/' + self._name + u'/context') as f:
ctx = f.read().strip()
return ctx
@property
def load(self):
"""Get the load of specified vserver."""
fl = u'/proc/virtual/' + self.context + u'/cvirt'
load = self.p.get_line_value(fl, u'loadavg:')
return load
@property
def uptime(self):
"""Get uptime of the vserver."""
fl = u'/proc/virtual/' + self.context + u'/cvirt'
bupx = self.p.get_line_value(fl, u'BiasUptime:')
if (bupx != 'None'):
bupx = float(bupx)
hupx = math.ceil(float(self.p.read_binary(u'/proc/uptime').split()[1]))
cupx = hupx - bupx
return self.p.convert_human(cupx)
return bupx
def _get_start_on_boot(self):
try:
mark = self._read_cfg(u'/apps/init/mark')
except IOError, e:
return False
if mark == u'default\n':
return True
elif mark == u'':
return False
else:
raise Error(u'Unexpected init mark: %r', mark)
def _set_start_on_boot(self, start_on_boot):
if start_on_boot:
self._write_cfg(u'/apps/init/mark', 0644, u'default\n')
else:
self._write_cfg(u'/apps/init/mark', 0644, u'')
start_on_boot = property(_get_start_on_boot, _set_start_on_boot)
def build(self, ip, fqdn, interface, method):
self.p.run([u'vserver', self._name, u'build',
u'--hostname', self._name,
u'--interface', interface,
u'-m'] + method)
self.write(u'/etc/hosts', 0644,
u'%s %s %s\n' % (ip, fqdn, self._name)
)
self._write_cfg(u'/fstab', 0644,
# disable ramdisk /tmp
u'none /proc proc defaults 0 0\n'
u'none /dev/pts devpts gid=5,mode=620 0 0\n'
)
self.running = True
def delete(self):
self.p.run([u'vserver', self._name, u'delete'],
input=u'Y\n')
def _test():
test = Host()
print 'Host kernel is',test.info['kernel']
print 'Uptime of host is', test.info['uptime']
lst = test.vserver_list()
print '%-10s %-20s %-10s %-20s %-20s' % ('Context', 'Name', 'Running', 'Load', 'Uptime')
for i in range(len(lst)):
vs = VServer(lst[i])
print '%-10s %-20s %-10s %-20s %-20s' % (vs.context, lst[i], vs.running, vs.load, vs.uptime)
if __name__ == '__main__':
_test()

Loading…
Cancel
Save