[Checkins] SVN: zc.zope3recipes/dev/zc/zope3recipes/ Added deployment support.

Jim Fulton jim at zope.com
Thu Jan 11 14:44:02 EST 2007


Log message for revision 71929:
  Added deployment support.
  

Changed:
  U   zc.zope3recipes/dev/zc/zope3recipes/README.txt
  U   zc.zope3recipes/dev/zc/zope3recipes/recipes.py

-=-
Modified: zc.zope3recipes/dev/zc/zope3recipes/README.txt
===================================================================
--- zc.zope3recipes/dev/zc/zope3recipes/README.txt	2007-01-11 18:25:48 UTC (rev 71928)
+++ zc.zope3recipes/dev/zc/zope3recipes/README.txt	2007-01-11 19:44:01 UTC (rev 71929)
@@ -706,14 +706,15 @@
     >>> cat('parts', 'instance', 'zdaemon.conf') 
     <runner>
       daemon on
+      directory /sample-buildout/parts/instance
       program /sample-buildout/parts/myapp/runzope -C /sample-buildout/parts/instance/zope.conf
-      socket-name /sample-buildout/parts/instance/zopectl.sock
+      socket-name /sample-buildout/parts/instance/zdaemon.sock
       transcript /sample-buildout/parts/instance/z3.log
     </runner>
     <BLANKLINE>
     <eventlog>
       <logfile>
-        path z3.log
+        path /sample-buildout/parts/instance/z3.log
       </logfile>
     <BLANKLINE>
     </eventlog>
@@ -781,6 +782,7 @@
     >>> cat('parts', 'instance', 'zdaemon.conf')
     <runner>
       daemon off
+      directory /sample-buildout/parts/instance
       program /sample-buildout/parts/myapp/runzope -C /sample-buildout/parts/instance/zope.conf
       socket-name /sample-buildout/parts/instance/sock
       transcript /dev/null
@@ -838,3 +840,173 @@
 do this by directing Zope's event log to standard output, where it is
 useful when running Zope in foreground mode and where it can be
 captured by the zdaemon transscript log.
+
+Unix Deployments
+----------------
+
+The instance recipe provides support for Unix deployments, as provided
+by the zc.recipe.deployment recipe.  A deployment part defines a number of
+options used by the instance recipe:
+
+etc-directory
+    The name of the directory where configurtion files should be
+    placed.  This defaults to /etc/NAME, where NAME is the deployment
+    name. 
+
+log-directory
+    The name of the directory where application instances should write
+    their log files.  This defaults to /var/log/NAME, where NAME is
+    the deployment name.
+
+run-directory
+    The name of the directory where application instances should put
+    their run-time files such as pid files and inter-process
+    communication socket files.  This defaults to /var/run/NAME, where
+    NAME is the deployment name.
+
+rc-directory
+    The name of the directory where run-control scripts should be
+    installed.
+
+user
+    The name of a user that processes should run as.
+
+The deployment recipe has to be run as root for various reasons, but
+we can create a faux deployment by providing a section with the needed
+data. Let's update our configuration to use a deployment.  We'll first
+create a faux installation root:
+
+    >>> root = tmpdir('root')
+    >>> mkdir(root, 'etc')
+    >>> mkdir(root, 'etc', 'myapp-run')
+    >>> mkdir(root, 'etc', 'init.d')
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ... 
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ... address = 8081
+    ... deployment = myapp-run
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ...
+    ... [myapp-run]
+    ... etc-directory = %(root)s/etc/myapp-run
+    ... rc-directory = %(root)s/etc/init.d
+    ... log-directory = %(root)s/var/log/myapp-run
+    ... run-directory = %(root)s/var/run/myapp-run
+    ... user = zope
+    ... ''' % globals())
+
+Here we've added a deployment section, myapp-run, and added a
+deployment option to our instance part telling the instance recipe to
+use the deployment.  If we rerun the buildout:
+
+    >>> print system(join('bin', 'buildout')),
+    buildout: Develop: /sample-buildout/demo1
+    buildout: Develop: /sample-buildout/demo2
+    buildout: Uninstalling instance
+    buildout: Updating database
+    buildout: Updating myapp
+    buildout: Installing instance
+
+The installe files will move.  We'll no-longer have the instance part:
+
+    >>> ls('parts')
+    d  database
+    d  myapp
+
+or the control script:
+
+    >>> ls('bin')
+    -  buildout
+
+Rather, we'll get our configuration files in the /etc/myapp-run directory:
+
+    >>> ls(root, 'etc', 'myapp-run')
+    -  instance-zdaemon.conf
+    -  instance-zope.conf
+
+Note that the instance name was added as a prefix to the file names,
+since we'll typically have additional instances in the deployment.
+
+The control script is in the init.d directory:
+
+    >>> ls(root, 'etc', 'init.d')
+    -  instance
+
+and the configuration files will be changed to reflect the deployment
+locations:
+
+    >>> cat(root, 'etc', 'myapp-run', 'instance-zope.conf')
+    site-definition /sample-buildout/parts/myapp/site.zcml
+    <BLANKLINE>
+    <zodb>
+      <filestorage>
+        path /sample-buildout/parts/database/Data.fs
+      </filestorage>
+    <BLANKLINE>
+    </zodb>
+    <BLANKLINE>
+    <server>
+      address 8081
+      type HTTP
+    </server>
+    <BLANKLINE>
+    <accesslog>
+      <logfile>
+        path /root/var/log/myapp-run/instance-access.log
+      </logfile>
+    <BLANKLINE>
+    </accesslog>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        formatter zope.exceptions.log.Formatter
+        path STDOUT
+      </logfile>
+    <BLANKLINE>
+    </eventlog>
+
+    >>> cat(root, 'etc', 'myapp-run', 'instance-zdaemon.conf')
+    <runner>
+      daemon on
+      directory /root/var/run/myapp-run
+      program /sample-buildout/parts/myapp/runzope -C /root/etc/myapp-run/instance-zope.conf
+      socket-name /root/var/run/myapp-run/instance-zdaemon.sock
+      transcript /root/var/log/myapp-run/instance-z3.log
+      user zope
+    </runner>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        path /root/var/log/myapp-run/instance-z3.log
+      </logfile>
+    <BLANKLINE>
+    </eventlog>

Modified: zc.zope3recipes/dev/zc/zope3recipes/recipes.py
===================================================================
--- zc.zope3recipes/dev/zc/zope3recipes/recipes.py	2007-01-11 18:25:48 UTC (rev 71928)
+++ zc.zope3recipes/dev/zc/zope3recipes/recipes.py	2007-01-11 19:44:01 UTC (rev 71929)
@@ -129,106 +129,133 @@
     def __init__(self, buildout, name, options):
         self.name, self.options = name, options
 
-        options['location'] = os.path.join(
-            buildout['buildout']['parts-directory'],
-            self.name,
-            )
-
         options['application-location'] = buildout[options['application']
                                                    ]['location']
 
-        options['bin-directory'] = buildout['buildout']['bin-directory']
-
         options['scripts'] = ''
         options['eggs'] = options.get('eggs', 'zdaemon\nsetuptools')
         self.egg = zc.recipe.egg.Egg(buildout, name, options)
+
+        deployment = self.deployment = options.get('deployment')
+        if deployment:
+            options['bin-directory'] = buildout[deployment]['rc-directory']
+            options['run-directory'] = buildout[deployment]['run-directory']
+            options['log-directory'] = buildout[deployment]['log-directory']
+            options['etc-directory'] = buildout[deployment]['etc-directory']
+            options['user'] = buildout[deployment]['user']
+        else:
+            options['bin-directory'] = buildout['buildout']['bin-directory']
+            options['run-directory'] = os.path.join(
+                buildout['buildout']['parts-directory'],
+                self.name,
+                )
             
+            
 
     def install(self):
         options = self.options
-        dest = conf_dir = log_dir = run_dir = options['location']
-        app_loc = options['application-location']
 
-        zope_conf_path = os.path.join(dest, 'zope.conf')
-        zdaemon_conf_path = os.path.join(dest, 'zdaemon.conf')
 
-        zope_conf = options.get('zope.conf', '')+'\n'
-        zope_conf = ZConfigParse(cStringIO.StringIO(zope_conf))
-        
-        zope_conf['site-definition'] = os.path.join(app_loc, 'site.zcml')
+        run_directory = options['run-directory']
+        deployment = self.deployment
+        if deployment:
+            zope_conf_path = os.path.join(options['etc-directory'],
+                                          self.name+'-zope.conf')
+            zdaemon_conf_path = os.path.join(options['etc-directory'],
+                                             self.name+'-zdaemon.conf')
+            event_log_path = os.path.join(options['log-directory'],
+                                          self.name+'-z3.log')
+            access_log_path = os.path.join(options['log-directory'],
+                                           self.name+'-access.log')
+            socket_path = os.path.join(run_directory,
+                                       self.name+'-zdaemon.sock')
+            creating = [zope_conf_path, zdaemon_conf_path,
+                        os.path.join(options['bin-directory'], self.name),
+                        ]
+        else:
+            zope_conf_path = os.path.join(run_directory, 'zope.conf')
+            zdaemon_conf_path = os.path.join(run_directory, 'zdaemon.conf')
+            event_log_path = os.path.join(run_directory, 'z3.log')
+            access_log_path = os.path.join(run_directory, 'access.log')
+            socket_path = os.path.join(run_directory, 'zdaemon.sock')
+            creating = [run_directory,
+                        os.path.join(options['bin-directory'], self.name),
+                        ]
+            if not os.path.exists(run_directory):
+                os.mkdir(run_directory)
 
-        for address in options.get('address', '').split():
-            zope_conf.sections.append(
-                ZConfigSection('server',
-                               data=dict(type='HTTP',
-                                         address=address,
-                                         ),
-                               )
-                )
-        if not [s for s in zope_conf.sections
-                if ('server' in s.type)]:
-            zope_conf.sections.append(
-                ZConfigSection('server',
-                               data=dict(type='HTTP',
-                                         address='8080',
-                                         ),
-                               )
-                )
+        try:
+            app_loc = options['application-location']
 
-        if not [s for s in zope_conf.sections if s.type == 'zodb']:
-            raise zc.buildout.UserError(
-                'No database sections have been defined.')
+            zope_conf = options.get('zope.conf', '')+'\n'
+            zope_conf = ZConfigParse(cStringIO.StringIO(zope_conf))
 
-        if not [s for s in zope_conf.sections
-                if s.type == 'accesslog']:
-            zope_conf.sections.append(
-                access_log(os.path.join(log_dir, 'access.log')))
+            zope_conf['site-definition'] = os.path.join(app_loc, 'site.zcml')
 
-                
-        if not [s for s in zope_conf.sections
-                if s.type == 'eventlog']:
-            zope_conf.sections.append(event_log('STDOUT'))
+            for address in options.get('address', '').split():
+                zope_conf.sections.append(
+                    ZConfigSection('server',
+                                   data=dict(type='HTTP',
+                                             address=address,
+                                             ),
+                                   )
+                    )
+            if not [s for s in zope_conf.sections
+                    if ('server' in s.type)]:
+                zope_conf.sections.append(
+                    ZConfigSection('server',
+                                   data=dict(type='HTTP',
+                                             address='8080',
+                                             ),
+                                   )
+                    )
 
+            if not [s for s in zope_conf.sections if s.type == 'zodb']:
+                raise zc.buildout.UserError(
+                    'No database sections have been defined.')
 
-        zdaemon_conf = options.get('zdaemon.conf', '')+'\n'
-        zdaemon_conf = ZConfigParse(cStringIO.StringIO(zdaemon_conf))
+            if not [s for s in zope_conf.sections if s.type == 'accesslog']:
+                zope_conf.sections.append(access_log(access_log_path))
 
-        defaults = {
-            'program': "%s -C %s" % (os.path.join(app_loc, 'runzope'),
-                                     zope_conf_path,
-                                     ),
-            'daemon': 'on',
-            'transcript': os.path.join(log_dir, 'z3.log'),
-            'socket-name': os.path.join(run_dir, 'zopectl.sock'),
-            }
-        runner = [s for s in zdaemon_conf.sections
-                  if s.type == 'runner']
-        if runner:
-            runner = runner[0]
-        else:
-            runner = ZConfigSection('runner')
-            zdaemon_conf.sections.insert(0, runner)
-        for name, value in defaults.items():
-            if name not in runner:
-                runner[name] = value
-        
-        if not [s for s in zdaemon_conf.sections
-                if s.type == 'eventlog']:
-            # No database, specify a default one
-            zdaemon_conf.sections.append(event_log2('z3.log'))
+            if not [s for s in zope_conf.sections if s.type == 'eventlog']:
+                zope_conf.sections.append(event_log('STDOUT'))
 
-        zdaemon_conf = str(zdaemon_conf)
 
-        self.egg.install()
-        requirements, ws = self.egg.working_set()
+            zdaemon_conf = options.get('zdaemon.conf', '')+'\n'
+            zdaemon_conf = ZConfigParse(cStringIO.StringIO(zdaemon_conf))
 
-        if not os.path.exists(dest):
-            os.mkdir(dest)
-            created = True
-        else:
-            created = False
-            
-        try:
+            defaults = {
+                'program': "%s -C %s" % (os.path.join(app_loc, 'runzope'),
+                                         zope_conf_path,
+                                         ),
+                'daemon': 'on',
+                'transcript': event_log_path,
+                'socket-name': socket_path,
+                'directory' : run_directory,
+                }
+            if deployment:
+                defaults['user'] = options['user']
+            runner = [s for s in zdaemon_conf.sections
+                      if s.type == 'runner']
+            if runner:
+                runner = runner[0]
+            else:
+                runner = ZConfigSection('runner')
+                zdaemon_conf.sections.insert(0, runner)
+            for name, value in defaults.items():
+                if name not in runner:
+                    runner[name] = value
+
+            if not [s for s in zdaemon_conf.sections
+                    if s.type == 'eventlog']:
+                # No database, specify a default one
+                zdaemon_conf.sections.append(event_log2(event_log_path))
+
+            zdaemon_conf = str(zdaemon_conf)
+
+            self.egg.install()
+            requirements, ws = self.egg.working_set()
+
             open(zope_conf_path, 'w').write(str(zope_conf))
             open(zdaemon_conf_path, 'w').write(str(zdaemon_conf))
 
@@ -249,12 +276,16 @@
                              ),
                 )
 
+            return creating
+
         except:
-            if created:
-                shutil.rmtree(dest)
+            for f in creating:
+                if os.path.is_dir(f):
+                    shutil.rmtree(f)
+                else:
+                    os.remove(f)
             raise
 
-        return dest, os.path.join(options['bin-directory'], self.name)
 
     def update(self):
         pass



More information about the Checkins mailing list