Commit 2d8c4212 authored by Marco Mariani's avatar Marco Mariani

experimental slapproxy-query command

parent b17a98d8
......@@ -34,18 +34,18 @@ setup(name=name,
packages=find_packages(),
include_package_data=True,
install_requires=[
'Flask', # used by proxy
'lxml', # needed to play with XML trees
'netaddr>=0.7.5', # to play safely with IPv6 prefixes
'netifaces', # to fetch information about network devices
'pyflakes', # For testing purposes
'setuptools', # namespaces
'supervisor', # slapgrid uses supervisor to manage processes
'unittest2',
'xml_marshaller>=0.9.3', # to unmarshall/marshall python objects to/from
# XML
'zope.interface', # slap library implementes interfaces
'zc.buildout',
'Flask', # used by proxy
'lxml', # needed to play with XML trees
'netaddr>=0.7.5', # to play safely with IPv6 prefixes
'netifaces', # to fetch information about network devices
'pyflakes', # For testing purposes
'setuptools', # namespaces
'supervisor', # slapgrid uses supervisor to manage processes
'unittest2',
'xml_marshaller>=0.9.3', # to unmarshall/marshall python objects to/from
# XML
'zope.interface', # slap library implementes interfaces
'zc.buildout',
] + additional_install_requires,
zip_safe=False, # proxy depends on Flask, which has issues with
# accessing templates
......@@ -54,6 +54,8 @@ setup(name=name,
# One entry point to control them all
'slapos = slapos.entry:main',
'slapos-watchdog = slapos.grid.watchdog:main',
'slapproxy = slapos.proxy:main',
'slapproxy-query = slapos.proxy.query:main',
# Deprecated entry points
'slapconsole = slapos.client:slapconsole',
'slapformat = slapos.format:main',
......@@ -63,7 +65,6 @@ setup(name=name,
'slapgrid-ur = slapos.grid.slapgrid:runUsageReport',
'slapgrid-supervisorctl = slapos.grid.svcbackend:supervisorctl',
'slapgrid-supervisord = slapos.grid.svcbackend:supervisord',
'slapproxy = slapos.proxy:main',
'bang = slapos.bang:main',
]
},
......
#!/opt/slapos/bin/py
# -*- coding: utf-8 -*-
# vim: set et sts=4:
import collections
import ConfigParser
from optparse import OptionParser, Option
import sys
import lxml.etree
import sqlite3
from slapos.proxy.db_version import DB_VERSION
class Parser(OptionParser):
"""
Parse all arguments.
"""
def __init__(self, usage=None, version=None):
"""
Initialize all options possibles.
"""
OptionParser.__init__(self, usage=usage, version=version,
option_list=[
Option("-u", "--database-uri",
type=str,
help="URI for sqlite database"),
Option('--show-instances',
help="View instance information",
default=False,
action="store_true"),
Option('--show-params',
help="View published parameters",
default=False,
action="store_true"),
Option('--show-network',
help="View network information",
default=False,
action="store_true"),
Option('--show-all',
help="View all information",
default=False,
action="store_true"),
])
def check_args(self):
"""
Check arguments
"""
(options, args) = self.parse_args()
if len(args) < 1:
self.error("Incorrect number of arguments")
return options, args[0]
class Config:
def setConfig(self, option_dict, configuration_file_path):
"""
Set options given by parameters.
"""
# Set options parameters
for option, value in option_dict.__dict__.items():
setattr(self, option, value)
# Load configuration file
configuration_parser = ConfigParser.SafeConfigParser()
configuration_parser.read(configuration_file_path)
# Merges the arguments and configuration
for section in ("slapproxy", "slapos"):
configuration_dict = dict(configuration_parser.items(section))
for key in configuration_dict:
if not getattr(self, key, None):
setattr(self, key, configuration_dict[key])
if not self.database_uri:
raise ValueError('database-uri is required.')
tbl_computer = 'computer' + DB_VERSION
tbl_software = 'software' + DB_VERSION
tbl_partition = 'partition' + DB_VERSION
tbl_partition_network = 'partition_network' + DB_VERSION
tbl_slave = 'slave' + DB_VERSION
null_str = u"-"
def print_table(qry, tablename, skip=None):
if skip is None:
skip = set()
columns = [c[0] for c in qry.description if c[0] not in skip]
rows = []
for row in qry.fetchall():
line = {}
for col in columns:
val = row[col]
if val is None:
val = null_str
line[col] = val.strip()
rows.append(line)
max_width = {col: len(col) for col in columns}
for row in rows:
for col in columns:
val = row[col]
max_width[col] = max(max_width[col], len(val) if val else 0)
hdr = [col.center(max_width[col]) for col in columns]
print
if rows:
print 'table %s:' % tablename,
else:
print 'table %s: empty' % tablename
return
if skip:
print 'skipping %s' % ', '.join(skip)
else:
print
print ' | '.join(hdr)
print '-+-'.join('-'*len(h) for h in hdr)
for row in rows:
cells = [row[col].ljust(max_width[col]) for col in columns]
print ' | '.join(cells)
def print_params(conn):
cur = conn.cursor()
print
qry = cur.execute("SELECT reference, partition_reference, software_type, connection_xml FROM %s" % tbl_partition)
for row in qry.fetchall():
if not row['connection_xml']:
continue
xml = str(row['connection_xml'])
print '%s: %s (type %s)' % (row['reference'], row['partition_reference'], row['software_type'])
instance = lxml.etree.fromstring(xml)
for parameter in list(instance):
name = parameter.get('id')
text = parameter.text
if text and name in ('ssh-key', 'ssh-public-key'):
text = text[:20] + '...' + text[-20:]
print ' %s = %s' % (name, text)
print
def print_computer_table(conn):
cur = conn.cursor()
qry = cur.execute("SELECT * FROM %s" % tbl_computer)
print_table(qry, tbl_computer)
def print_software_table(conn):
cur = conn.cursor()
qry = cur.execute("SELECT * FROM %s" % tbl_software)
print_table(qry, tbl_software)
def print_partition_table(conn):
cur = conn.cursor()
qry = cur.execute("SELECT * FROM %s WHERE slap_state<>'free'" % tbl_partition)
print_table(qry, tbl_partition, skip=['xml', 'connection_xml', 'slave_instance_list'])
def print_slave_table(conn):
cur = conn.cursor()
qry = cur.execute("SELECT * FROM %s" % tbl_slave)
print_table(qry, tbl_slave, skip=['connection_xml'])
def print_tables(conn):
print_computer_table(conn)
print_software_table(conn)
print_partition_table(conn)
print_slave_table(conn)
def print_network(conn):
print
cur = conn.cursor()
addr = collections.defaultdict(list)
qry = cur.execute("""
SELECT * FROM %s
WHERE partition_reference NOT IN (
SELECT reference
FROM %s
WHERE slap_state='free')
""" % (tbl_partition_network, tbl_partition))
for row in qry:
addr[row['partition_reference']].append(row['address'])
for partition_reference in sorted(addr.keys()):
addresses = addr[partition_reference]
print '%s: %s' % (partition_reference, ', '.join(addresses))
def run(config):
conn = sqlite3.connect(config.database_uri)
conn.row_factory = sqlite3.Row
fn = []
if config.show_all or config.show_instances:
fn.append(print_tables)
if config.show_all or config.show_params:
fn.append(print_params)
if config.show_all or config.show_network:
fn.append(print_network)
if fn:
for f in fn:
f(conn)
else:
print 'usage: %s [ --show-params | --show-network | --show-instances | --show-all ]' % sys.argv[0]
def main():
"Run default configuration."
usage = "usage: %s [options] CONFIGURATION_FILE" % sys.argv[0]
try:
# Parse arguments
config = Config()
config.setConfig(*Parser(usage=usage).check_args())
run(config)
return_code = 0
except SystemExit, err:
# Catch exception raise by optparse
return_code = err
sys.exit(return_code)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment