[Erp5-report] r33862 luke - in /erp5/trunk/utils/erp5.timmy: ./ src/ src/erp5/ src/erp5/tim...

nobody at svn.erp5.org nobody at svn.erp5.org
Thu Mar 18 14:05:32 CET 2010


Author: luke
Date: Thu Mar 18 14:05:30 2010
New Revision: 33862

URL: http://svn.erp5.org?rev=33862&view=rev
Log:
 - initial version

Added:
    erp5/trunk/utils/erp5.timmy/
    erp5/trunk/utils/erp5.timmy/CHANGES.txt   (with props)
    erp5/trunk/utils/erp5.timmy/README.txt   (with props)
    erp5/trunk/utils/erp5.timmy/setup.py
    erp5/trunk/utils/erp5.timmy/src/
    erp5/trunk/utils/erp5.timmy/src/erp5/
    erp5/trunk/utils/erp5.timmy/src/erp5/__init__.py
    erp5/trunk/utils/erp5.timmy/src/erp5/timmy/
    erp5/trunk/utils/erp5.timmy/src/erp5/timmy/__init__.py
    erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/
    erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/conversion-server-template.cfg
    erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/instance-template.cfg
    erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/main-template.cfg
    erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/mysql-database-template.cfg
    erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/mysql-server-template.cfg
    erp5/trunk/utils/erp5.timmy/src/erp5/timmy/timmy.py
    erp5/trunk/utils/erp5.timmy/svn-commit.tmp

Added: erp5/trunk/utils/erp5.timmy/CHANGES.txt
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.timmy/CHANGES.txt?rev=33862&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.timmy/CHANGES.txt (added)
+++ erp5/trunk/utils/erp5.timmy/CHANGES.txt [utf8] Thu Mar 18 14:05:30 2010
@@ -1,0 +1,3 @@
+2010-03-18 Luke
+---------------
+Initial version 0.1

Propchange: erp5/trunk/utils/erp5.timmy/CHANGES.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Added: erp5/trunk/utils/erp5.timmy/README.txt
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.timmy/README.txt?rev=33862&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.timmy/README.txt (added)
+++ erp5/trunk/utils/erp5.timmy/README.txt [utf8] Thu Mar 18 14:05:30 2010
@@ -1,0 +1,18 @@
+timmy
+=====
+
+TioLive Instance Management System oriented on pull method from remote servers.
+
+This tool allows to manage various instances (Zope, Mysql, Oood) to be defined
+on some remote server and manage them on local server.
+
+It reuses supervisord (http://supervisord.org/) to manage non Zope Instances.
+
+timmy and buildout
+------------------
+
+Timmy is installed and bootstraped by buildout. Then it reuses same buildout
+to manage instances of various kinds.
+
+For now it is assumed that buildout will provide all needed requirements. As
+timmy will become more mature it will be able to fetch requirements by itself.

Propchange: erp5/trunk/utils/erp5.timmy/README.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Added: erp5/trunk/utils/erp5.timmy/setup.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.timmy/setup.py?rev=33862&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.timmy/setup.py (added)
+++ erp5/trunk/utils/erp5.timmy/setup.py [utf8] Thu Mar 18 14:05:30 2010
@@ -1,0 +1,38 @@
+from setuptools import setup, find_packages
+
+name = "timmy"
+version = '0.1'
+
+def read(name):
+    return open(name).read()
+
+long_description=(
+        read('README.txt')
+        + '\n' +
+        read('CHANGES.txt')
+    )
+
+setup(
+    name = name,
+    version = version,
+    author = "Lukasz Nowak",
+    author_email = "luke at nexedi.com",
+    description = "timmy - TioLive Instance Management System oriented on "\
+        "pull method from remote servers",
+    long_description=long_description,
+    license = "GPL",
+    keywords = "instance management",
+    classifiers=[
+      ],
+    packages = find_packages('src'),
+    include_package_data = True,
+    package_dir = {'':'src'},
+    namespace_packages = ['erp5', 'erp5.timmy'],
+    install_requires = [
+    ],
+    zip_safe=False,
+    entry_points = """
+    [console_scripts]
+    timmy = erp5.timmy.timmy:run
+    """,
+    )

Added: erp5/trunk/utils/erp5.timmy/src/erp5/__init__.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.timmy/src/erp5/__init__.py?rev=33862&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.timmy/src/erp5/__init__.py (added)
+++ erp5/trunk/utils/erp5.timmy/src/erp5/__init__.py [utf8] Thu Mar 18 14:05:30 2010
@@ -1,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: erp5/trunk/utils/erp5.timmy/src/erp5/timmy/__init__.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.timmy/src/erp5/timmy/__init__.py?rev=33862&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.timmy/src/erp5/timmy/__init__.py (added)
+++ erp5/trunk/utils/erp5.timmy/src/erp5/timmy/__init__.py [utf8] Thu Mar 18 14:05:30 2010
@@ -1,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/conversion-server-template.cfg
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/conversion-server-template.cfg?rev=33862&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/conversion-server-template.cfg (added)
+++ erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/conversion-server-template.cfg [utf8] Thu Mar 18 14:05:30 2010
@@ -1,0 +1,6 @@
+[%{ID}]
+<= conversion-server-template
+
+[configuration]
+oood_host = %{IP_ADDRESS}
+oood_port = %{TCP_PORT}

Added: erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/instance-template.cfg
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/instance-template.cfg?rev=33862&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/instance-template.cfg (added)
+++ erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/instance-template.cfg [utf8] Thu Mar 18 14:05:30 2010
@@ -1,0 +1,31 @@
+[%{ID}]
+<= zope-instance-template
+instancehome = ${buildout:var-directory}/%{ID}
+user = %{INSTANCE_ADMIN_USER}:%{INSTANCE_ADMIN_PASSWORD}
+http-address = %{TCP_PORT}
+# Disabled installing of BT5 during site creation
+bt5 =
+bt5-path =
+
+# List of Business Templates which will be installed on running site
+required-bt5 =
+ %{BT5_LIST}
+bt5-url =
+
+# TODO: protect fragile information
+mysql_create_database = false
+
+mysql_database_name = %{MYSQL_DATABASE}
+mysql_user = %{MYSQL_USER}
+mysql_password = %{MYSQL_PASSWORD}
+mysql_host = %{MYSQL_HOST}
+mysql_port = %{MYSQL_PORT}
+
+erp5_sql_connection_string = ${:mysql_database_name}@${:mysql_host}:${:mysql_port} ${:mysql_user} ${:mysql_password}
+
+products =
+  ${:instancehome}/Products
+  ${software_definition:products-cmf15}
+  ${software_definition:products-deps}
+  ${software_definition:products-erp5}
+  ${software_definition:products-other}

Added: erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/main-template.cfg
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/main-template.cfg?rev=33862&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/main-template.cfg (added)
+++ erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/main-template.cfg [utf8] Thu Mar 18 14:05:30 2010
@@ -1,0 +1,8 @@
+[buildout]
+extends =
+  %{BASE_PROFILE}
+  %{INSTANCE_PROFILE_LIST}
+
+parts +=
+  %{INSTANCE_PART_LIST}
+

Added: erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/mysql-database-template.cfg
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/mysql-database-template.cfg?rev=33862&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/mysql-database-template.cfg (added)
+++ erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/mysql-database-template.cfg [utf8] Thu Mar 18 14:05:30 2010
@@ -1,0 +1,9 @@
+[%{ID}]
+<= mysql-database-template
+mysql_database_name = %{ID}
+mysql_user = %{MYSQL_USER}
+mysql_password = %{MYSQL_PASSWORD}
+
+# Luke do not know where to put below for now
+mysql_superuser = root
+mysql_superpassword =

Added: erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/mysql-server-template.cfg
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/mysql-server-template.cfg?rev=33862&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/mysql-server-template.cfg (added)
+++ erp5/trunk/utils/erp5.timmy/src/erp5/timmy/examples/mysql-server-template.cfg [utf8] Thu Mar 18 14:05:30 2010
@@ -1,0 +1,6 @@
+[%{ID}]
+<= mysql-server-template
+
+[configuration]
+mysql_host = %{IP_ADDRESS}
+mysql_port = %{TCP_PORT}

Added: erp5/trunk/utils/erp5.timmy/src/erp5/timmy/timmy.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.timmy/src/erp5/timmy/timmy.py?rev=33862&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.timmy/src/erp5/timmy/timmy.py (added)
+++ erp5/trunk/utils/erp5.timmy/src/erp5/timmy/timmy.py [utf8] Thu Mar 18 14:05:30 2010
@@ -1,0 +1,364 @@
+import uuid, os, xmlrpclib, subprocess, logging
+from string import Template
+from optparse import OptionParser
+
+REQUIRED_TEMPLATE_LIST = [
+  'instance-template.cfg',
+  'main-template.cfg'
+]
+
+SUPERVISORD = os.path.join('var', 'bin', 'supervisord')
+SUPERVISORCTL = os.path.join('var', 'bin', 'supervisorctl')
+
+class XMLRPCServer(object):
+  def __init__(self, server_url, client_key):
+    self.client_key = client_key
+    self.server_url = server_url
+
+  def call(self, method, *args):
+    server = xmlrpclib.ServerProxy(self.server_url)
+    args = list(args)
+    args.insert(0, self.client_key)
+    return getattr(server, method)(*args)
+
+class PercentTemplate(Template):
+  delimiter = '%'
+
+def generateServerKey():
+  return str(uuid.uuid4())
+
+def getServerKey(key_file):
+  # TODO:
+  #  * make key safe (600)
+  #  * make generation safe (remove file in case of problem)
+  if os.path.exists(key_file):
+    return file(key_file).readlines()[0].strip()
+  new_uid = generateServerKey()
+  file(key_file, 'w').write(new_uid)
+  return new_uid
+
+def parseOptions():
+  parser = OptionParser()
+  parser.add_option("-k", "--key-file",
+    help="File with server key")
+
+  parser.add_option("-s", "--server-url",
+    help="URL of provisioning server")
+
+  parser.add_option("-b", "--base-profile",
+    help="Base profile")
+
+  parser.add_option("-t", "--template-directory",
+    help="Directory with templates")
+
+  parser.add_option("-o", "--main-output",
+    help="Main profile output, which will be run by buildout")
+
+  parser.add_option("-d", "--instances-directory",
+    help="Instances profiles output, must be existing directory")
+
+  parser.add_option("-r", "--buildout-binary",
+    help="Buildout binary to run")
+
+  (options, args) = parser.parse_args()
+  required_option_list = [
+      'base_profile',
+      'buildout_binary',
+      'instances_directory',
+      'key_file',
+      'main_output',
+      'server_url',
+      'template_directory',
+    ]
+  for o in required_option_list:
+    if not getattr(options, o, None):
+      parser.error('All options are required, missing "%s".' % o)
+  for filepath in options.base_profile, options.instances_directory:
+    if not os.path.exists(filepath):
+      raise ValueError('Cannot find "%s"' % filepath)
+  missing_template_list = []
+  for filename in REQUIRED_TEMPLATE_LIST:
+    filepath = os.path.join(options.template_directory, filename)
+    if not os.path.exists(filepath):
+      missing_template_list.append(filepath)
+  if missing_template_list:
+    raise ValueError('Missing templates: %s' % ','.join(missing_template_list))
+  return options, args
+
+def updateBaseProfile(template_directory, file_output, base_profile,
+    instances_directory, instance_dict_list):
+  # TODO:
+  #  * cleanup in case of problem
+  #  * use safe update of output file
+  template_data = ''.join(file(os.path.join(template_directory,
+    'main-template.cfg')).readlines())
+  template = PercentTemplate(template_data)
+  replacement_dict = {
+    'BASE_PROFILE': base_profile,
+    'INSTANCE_PROFILE_LIST': [],
+    'INSTANCE_PART_LIST': []
+  }
+  for instance in [q for q in instance_dict_list if q['TYPE'] == 'Mysql Server']:
+    replacement_dict['INSTANCE_PROFILE_LIST'].append('%s/%s.cfg' % (
+      instances_directory, instance['ID']))
+    replacement_dict['INSTANCE_PART_LIST'].append(instance['ID'])
+
+  for instance in [q for q in instance_dict_list if q['TYPE'] == 'Mysql Database']:
+    replacement_dict['INSTANCE_PROFILE_LIST'].append('%s/%s.cfg' % (
+      instances_directory, instance['ID']))
+    replacement_dict['INSTANCE_PART_LIST'].append(instance['ID'])
+
+  for instance in [q for q in instance_dict_list if q['TYPE'] == 'Conversion Server']:
+    replacement_dict['INSTANCE_PROFILE_LIST'].append('%s/%s.cfg' % (
+      instances_directory, instance['ID']))
+    replacement_dict['INSTANCE_PART_LIST'].append(instance['ID'])
+
+  for instance in [q for q in instance_dict_list if q['TYPE'] == 'Zope Instance']:
+    replacement_dict['INSTANCE_PROFILE_LIST'].append('%s/%s.cfg' % (
+      instances_directory, instance['ID']))
+    replacement_dict['INSTANCE_PART_LIST'].append(instance['ID'])
+
+  replacement_dict['INSTANCE_PROFILE_LIST'] = '\n  '.join(
+      replacement_dict['INSTANCE_PROFILE_LIST'])
+  replacement_dict['INSTANCE_PART_LIST'] = '\n  '.join(
+      replacement_dict['INSTANCE_PART_LIST'])
+  out = file(file_output, 'w')
+  out.write(template.substitute(replacement_dict))
+  out.close()
+
+def updateInstanceProfiles(template_directory, output_directory, instance_dict_list):
+  template_mapping = {
+    'Zope Instance': 'instance-template.cfg',
+    'Mysql Server': 'mysql-server-template.cfg',
+    'Mysql Database': 'mysql-database-template.cfg',
+    'Conversion Server': 'conversion-server-template.cfg',
+  }
+  for instance in instance_dict_list:
+    template_data = ''.join(file(os.path.join(template_directory,
+      template_mapping[instance['TYPE']])).readlines())
+
+    template = PercentTemplate(template_data)
+    if 'BT5_LIST' in instance:
+      instance['BT5_LIST'] = '\n  '.join(instance['BT5_LIST'])
+    if 'IP_ADDRESS_LIST' in instance:
+      if instance['IP_ADDRESS_LIST']:
+        instance['IP_ADDRESS'] = instance['IP_ADDRESS_LIST'][0]
+    out = file(os.path.join(output_directory, '%s.cfg' % instance['ID']), 'w')
+    out.write(template.substitute(instance))
+    out.close()
+
+def runBuildout(buildout, profile):
+  invoke_list = [buildout, '-c', profile]
+  logging.info('invoking %s' % ' '.join(invoke_list))
+  popen = subprocess.Popen([buildout, '-c', profile],
+      stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+  (result_std, result_err) = popen.communicate()
+  # TODO: check that site is accesible in Data.fs, we cannot belive in
+  #       Popen.returncode, as subprocesses of subprocesses are not handled
+  #       properly
+
+  # TODO: parse result_std and result_err
+
+  logging.info('Standard output:')
+  logging.info(result_std)
+  logging.info('Error output:')
+  logging.info(result_err)
+
+class Partition(object):
+  # generic
+  def __init__(self, partition_id, partition_type):
+    self.partition_id = partition_id
+    self.partition_type = partition_type.replace(' ', '')
+    getattr(self, '%s' % self.partition_type)(partition_id)
+
+  def install(self):
+    return getattr(self, 'install_%s' % self.partition_type)()
+
+  def start(self):
+    return getattr(self, 'start_%s' % self.partition_type)()
+
+  def stop(self):
+    return getattr(self, 'stop_%s' % self.partition_type)()
+
+  def getPartitionState(self):
+    return getattr(self, 'getPartitionState_%s' % self.partition_type)()
+
+  # Specific code - candidates for plugins
+  # Mysql Database
+  def MysqlDatabase(self, partition_id):
+    pass
+
+  def install_MysqlDatabase(self):
+    return self.getPartitionState_MysqlDatabase()
+
+  def start_MysqlDatabase(self):
+    return self.getPartitionState_MysqlDatabase()
+
+  def stop_MysqlDatabase(self):
+    return self.getPartitionState_MysqlDatabase()
+
+  def getPartitionState_MysqlDatabase(self):
+    return 'reportError', 'NotImplemented'
+
+  # Mysql Server
+  def MysqlServer(self, partition_id):
+    self.control_script = SUPERVISORCTL
+
+  def install_MysqlServer(self):
+    return self.getPartitionState_MysqlServer()
+
+  def start_MysqlServer(self):
+    return self.getPartitionState_MysqlServer()
+
+  def stop_MysqlServer(self):
+    return self.getPartitionState_MysqlServer()
+
+  def getPartitionState_MysqlServer(self):
+    return self.getPartitionState_Supervised('mysql')
+
+  # Conversion Server
+  def ConversionServer(self, partition_id):
+    self.control_script = SUPERVISORCTL
+
+  def install_ConversionServer(self):
+    return self.getPartitionState_ConversionServer()
+
+  def start_ConversionServer(self):
+    return self.getPartitionState_ConversionServer()
+
+  def stop_ConversionServer(self):
+    return self.getPartitionState_ConversionServer()
+
+  def getPartitionState_Supervised(self, name):
+    # XXX: Use XML RPC
+    popen = subprocess.Popen([self.control_script, 'status', name],
+        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    (result_std, result_err) = popen.communicate()
+    if 'RUNNING' in result_std:
+      return 'reportStarted', 'supervised'
+    if 'STARTING' in result_std:
+      return 'reportStarting', 'supervised'
+    if 'STOPPING' in result_std:
+      return 'reportStopping', 'supervised'
+    if 'STOPPED' in result_std:
+      return 'reportStopped', 'supervised'
+    return 'reportError', 'supervised: [std: %s] [err: %s]' % (result_std, result_err)
+
+  def getPartitionState_ConversionServer(self):
+    return self.getPartitionState_Supervised('oood')
+
+  # Zope Instance related
+  def ZopeInstance(self, partition_id):
+    self.control_script = os.path.join('var', partition_id, 'bin', 'zopectl')
+
+  def _zopectl_subprocess(self, action):
+    popen = subprocess.Popen([self.control_script, action],
+        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    return list(popen.communicate()) + [popen.returncode]
+
+  def install_ZopeInstance(self):
+    # XXX: Very simple way to know if partition was installed
+    if os.path.exists(self.control_script):
+      return 'reportInstalled', ''
+    else:
+      return 'reportError', 'Installation failed'
+
+  def start_ZopeInstance(self):
+    if self.getPartitionState()[0] == 'started':
+      return 'reportStarted', ''
+    logging.info('Starting instance %s' % self.partition_id)
+    (result_std, result_err, returncode) = self._zopectl_subprocess('start')
+    if returncode:
+      return 'reportError', 'failed to start'
+    return 'reportStarting', ''
+
+  def stop_ZopeInstance(self):
+    if self.getPartitionState()[0] == 'stopped':
+      return 'reportStopped', ''
+    logging.info('Stopping instance %s' % self.partition_id)
+    (result_std, result_err, returncode) = self._zopectl_subprocess('stop')
+    if returncode:
+      return 'reportError', 'failed to stop'
+    return 'reportStopping', ''
+
+  def getPartitionState_ZopeInstance(self):
+    logging.info('Fetching status of instance %s' % self.partition_id)
+    (result_std, result_err, returncode) = self._zopectl_subprocess('status')
+    if result_std.startswith('program running'):
+      return 'started', ''
+    elif 'not running' in result_std:
+      return 'stopped', ''
+    else:
+      return 'error', '%s %s' % (result_std, result_err)
+
+class Helper(object):
+  def manageNothing(self, partition, server):
+    pass
+
+  def manageInstall(self, partition, server):
+    result = partition.install()
+    if result:
+      server.call('updatePartitionState', partition.partition_id,
+        *result)
+
+  def manageStart(self, partition, server):
+    result = partition.start()
+    if result:
+      server.call('updatePartitionState', partition.partition_id,
+        *result)
+
+  def manageStop(self, partition, server):
+    result = partition.stop()
+    if result:
+      server.call('updatePartitionState', partition.partition_id,
+        *result)
+
+  def manageStatus(self, partition, server):
+    result = partition.getPartitionState()
+    if result:
+      server.call('updatePartitionState', partition.partition_id,
+        *result)
+
+def run():
+  logging.basicConfig(level=logging.INFO)
+  (options, args) = parseOptions()
+  server = XMLRPCServer(options.server_url, getServerKey(options.key_file))
+  partition_dict_list = server.call('getComputerConfigurationDictList')
+  # prepare - run supervisor
+  subprocess.call(SUPERVISORD)
+  # 1a pass - main profile
+  updateBaseProfile(options.template_directory, options.main_output,
+      options.base_profile, options.instances_directory, partition_dict_list)
+  # 1b pass - instance profiles
+  updateInstanceProfiles(options.template_directory,
+      options.instances_directory, partition_dict_list)
+  # 2 pass - run buildout
+  runBuildout(options.buildout_binary, options.main_output)
+
+  # 3 pass - manage instances
+  updated_partition_list = []
+  helper = Helper()
+  for partition_dict in partition_dict_list:
+    # install
+    # stop
+    # switch to special management
+    # start
+    partition = Partition(partition_dict['ID'], partition_dict['TYPE'])
+    switcher_dict = dict(
+        start = 'manageStart',
+        stop = 'manageStop',
+        nothing = 'manageNothing',
+        install = 'manageInstall',
+    )
+    action = getattr(helper, switcher_dict[partition_dict['ACTION']])
+    action(partition, server)
+
+  # force supervisor to reload its configuration
+  subprocess.call([SUPERVISORCTL, 'update'])
+
+if __name__ == '__main__':
+  # example invocation:
+  # bin/timmy -k key.key -s http://server:port/portal_grids/tiolive \
+  #  -b timmy-base.cfg -t timmy-templates/ \
+  #  -o timmy-controller.cfg -d timmy-instances -r bin/buildout
+  run()

Added: erp5/trunk/utils/erp5.timmy/svn-commit.tmp
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.timmy/svn-commit.tmp?rev=33862&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.timmy/svn-commit.tmp (added)
+++ erp5/trunk/utils/erp5.timmy/svn-commit.tmp [utf8] Thu Mar 18 14:05:30 2010
@@ -1,0 +1,4 @@
+
+--This line, and those below, will be ignored--
+
+D    https://svn.erp5.org/repos/webproject/trunk/utils/erp5.timmy




More information about the Erp5-report mailing list