[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