############################################################################## # # Copyright (c) 2010 ViFiB SARL and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## import os import time import sys import shutil import MySQLdb import sys import argparse def run(): """Start the instance runner. this may run a python script, move or/and rename file or directory when dondition is filled. the condition may be when file exist or when an entry exist into database. """ parser = argparse.ArgumentParser(description='Lamp instance configurator for SlapOs') group = parser.add_mutually_exclusive_group() group.add_argument('-f', action='store', dest='file_token', help='The condition is true when file FILE_TOKEN is found', default=None) group.add_argument('-d', action='store', dest='token', default='appdb', help="The condition is true when an entry is found in to database TOKEN") parser.add_argument('-H', action='store', default="localhost", dest='mysql_host', help='Speficify the MySQL host') parser.add_argument('-u', action='store', default="root", dest='mysql_user', help='Speficify the MySQL user') parser.add_argument('-P', action='store', default=3306, dest='mysql_port', type=int, help='Speficify the MySQL port') parser.add_argument('-p', action='store', default="", dest='mysql_password', help='Speficify the MySQL password') parser.add_argument('--target-directory', '-t', action='store', default="", dest='target_directory', help='Specifie the target directory to be used') parser.add_argument('--table', '-s', action='store', default="**", dest='table', help='Specifie the table for database TOKEN to use when -d option is used') parser.add_argument('--cond', '-c', action='store', default="1", type=str, dest='condition', help='Specifie the SQL condition to use when -d option is used') subparsers = parser.add_subparsers(help='commands') # A delete command delete_parser = subparsers.add_parser('delete', help='Remove file or directory') delete_parser.add_argument('delete_target', action='store', help='The list of file or directory to remove', nargs='+') # A rename command rename_parser = subparsers.add_parser('rename', help='Rename SOURCE to DESTINATION') rename_parser.add_argument('source', action='store', help='the source to be rename') rename_parser.add_argument('destination', action='store', help='the new name of SOURCE after rename') rename_parser.add_argument('--chmod', action='store', help='The Mode to apply after rename file or directory', default=None, dest='mode') # A python script command script_parser = subparsers.add_parser('run', help='Run python script') script_parser.add_argument('script', action='store', help='The path of python script to execute') script_parser.add_argument('-v', action='store', help='Other argument to pass to the script', nargs='+', dest='args') # A SQL script command sql_parser = subparsers.add_parser('sql', help='Run SQL script') sql_parser.add_argument('sql_script', action='store', help='The path of python script to execute') sql_parser.add_argument('-v', action='store', help='Other argument to pass to the script', nargs='+', dest='args') #A chmod command chmod_parser = subparsers.add_parser('chmod', help='Set the mode of file or directory') chmod_parser.add_argument('mode', action='store', help='the mode to apply to TARGET') chmod_parser.add_argument('chmod_target', action='store', help='the file or directory to change mode', nargs='+') result = parser.parse_args() arguments = dict(result._get_kwargs()) if arguments['token'] == None and arguments['file_token'] == None: print "lampconfigure: Error: Please specify where condition will be taken, use -d or -f option" return setup(arguments) def setup(arguments): timeout = 5; while True: if not checkAction(arguments): print "Waiting for 3s and retrying" time.sleep(3) continue time.sleep(timeout) if arguments.has_key('delete_target'): delete(arguments) if arguments.has_key('source'): rename(arguments) if arguments.has_key('script'): run_script(arguments) if arguments.has_key('sql_script'): run_sql_script(arguments) if arguments.has_key('chmod_target'): chmod(arguments) return def checkAction(arguments): """Check if condition is filled. If token is string(that represent a path), the function check if file exist otherwise token is a dictionary and mysql_config is used to check condition into database """ if arguments['file_token'] == None: try: conn = MySQLdb.connect (host = arguments['mysql_host'], port = arguments['mysql_port'], user = arguments['mysql_user'], passwd = arguments['mysql_password'], db = arguments['token']) except Exception, ex: #Mysql is not ready yet?... print ex.message return False if arguments['table'] == "**": #only detect if mysql has been started conn.close() return True cursor = conn.cursor () cursor.execute("SHOW TABLES LIKE '%" + arguments['table'] + "'") #Check if table has been created row = cursor.fetchone () if row == None: conn.close() return True else: arguments['table'] = row[0] cursor.execute ("SELECT * FROM " + arguments['table'] + " WHERE " + arguments['condition']) row = cursor.fetchone () conn.close() if row == None: return True else: return False else: return not os.path.exists(os.path.join(arguments['target_directory'], arguments['file_token'])) def rename(arguments): source = os.path.join(arguments['target_directory'], arguments['source']) destination = os.path.join(arguments['target_directory'], arguments['destination']) if not os.path.exists(source): print "Error when moving: '%s': no such file or directory" % source return os.rename(source, destination) if arguments['mode'] != None: os.chmod(destination, int(arguments['mode'], 8)) def delete(arguments): for path in arguments['delete_target']: path = os.path.join(arguments['target_directory'], path) if not os.path.exists(path): print "Error when deleting: '%s': no such file or directory" % path continue if os.path.isdir(path): shutil.rmtree(path) else: os.remove(path) def run_script(arguments): script = os.path.join(arguments['target_directory'], arguments['script']) print 'Running script: %s' % script if os.path.exists(script): import subprocess #run python script with predefined data data = [sys.executable, script, str(arguments['mysql_port']), arguments['mysql_host'], arguments['mysql_user'], arguments['mysql_password']] if arguments['args'] != None: data = data + arguments['args'] result = subprocess.Popen(data, env={'PYTHONPATH': ':'.join(sys.path)}) result.wait() else: print "Error: can not read file '%s'" % script def run_sql_script(arguments): script = os.path.join(arguments['target_directory'], arguments['sql_script']) print 'Running SQL script: %s' % script if os.path.exists(script): conn = MySQLdb.connect(host=arguments['mysql_host'], port=int(arguments['mysql_port']), user=arguments['mysql_user'], passwd=arguments['mysql_password'], # XXX ugly, to simplify db=arguments['args'][0]) cursor = conn.cursor () with open(script, 'r') as f: sql_script = f.read() cursor.execute(sql_script) conn.close() else: print "Error: can not read file '%s'" % script def chmod(arguments): for path in arguments['chmod_target']: path = os.path.join(arguments['target_directory'], path) if not os.path.exists(path): print "Error when changing mode: '%s': no such file or directory" % path continue os.chmod(path, int(arguments['mode'], 8))