__init__.py 8.62 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
##############################################################################
#
# 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():
25
  """Start the instance runner. this may run a python script, move or/and rename
26 27 28 29 30 31 32 33 34 35
  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",
Alain Takoudjou's avatar
Alain Takoudjou committed
36
                    dest='mysql_host', help='Speficify the MySQL host')
37
  parser.add_argument('-u', action='store', default="root",
Alain Takoudjou's avatar
Alain Takoudjou committed
38
                    dest='mysql_user', help='Speficify the MySQL user')
39 40
  parser.add_argument('-P', action='store', default=3306,
                    dest='mysql_port', type=int,
Alain Takoudjou's avatar
Alain Takoudjou committed
41
                    help='Speficify the MySQL port')
42
  parser.add_argument('-p', action='store', default="",
Alain Takoudjou's avatar
Alain Takoudjou committed
43
                    dest='mysql_password', help='Speficify the MySQL password')
44 45 46 47 48 49 50 51 52
  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')
53
  delete_parser.add_argument('delete_target', action='store', help='The list of file or directory to remove',
54 55 56 57 58 59
                             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',
Alain Takoudjou's avatar
Alain Takoudjou committed
60
                             default=None, dest='mode')
61 62 63 64
  # 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')
65 66 67 68 69 70

  # 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')

71 72
  #A chmod command
  chmod_parser = subparsers.add_parser('chmod', help='Set the mode of file or directory')
Alain Takoudjou's avatar
Alain Takoudjou committed
73
  chmod_parser.add_argument('mode', action='store', help='the mode to apply to TARGET')
74 75 76 77 78 79 80 81
  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)
82

83 84 85 86 87 88 89 90 91 92
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)
93

94 95
    if arguments.has_key('source'):
      rename(arguments)
96

97 98
    if arguments.has_key('script'):
      run_script(arguments)
99 100 101 102

    if arguments.has_key('sql_script'):
      run_sql_script(arguments)

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
    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()
131
      return True
132 133 134 135 136 137 138
    else:
      arguments['table'] = row[0]
    cursor.execute ("SELECT * FROM " + arguments['table'] + " WHERE " + arguments['condition'])
    row = cursor.fetchone ()
    conn.close()
    if row == None:
      return True
139 140
    else:
      return False
141
  else:
142 143
    return not os.path.exists(os.path.join(arguments['target_directory'], arguments['file_token']))

144 145 146 147 148 149 150 151
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:
Alain Takoudjou's avatar
Alain Takoudjou committed
152
    os.chmod(destination, int(arguments['mode'], 8))
153

154 155 156 157 158 159 160 161 162 163 164 165 166
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'])
167
  print 'Running script: %s' % script
168 169 170 171 172 173 174 175 176 177 178 179
  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
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202


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



203 204 205 206 207 208
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
Alain Takoudjou's avatar
Alain Takoudjou committed
209
    os.chmod(path, int(arguments['mode'], 8))