Search code examples
deploymentplonecontinuous-deploymentzopezodb

Zope/Plone code reload after deployment on production


Is there a way to reload the code without restarting Zope when in Production ? New features are implemented almost once in 2 days and have to be uploaded to the server. The only way it works currently is by restarting the zeo server and all instances. Can't use "plone.reload" as it only works in the development environment when the debug mode is on. Below is the buildout.cfg content

[buildout]


  parts =
#    instance
        zeo
        client1
        client2
        client3
        zopepy
        zopeskel
        test
#    mysql
#    varnish-build
#    varnish
    supervisor
    pidproxy

extends =
    https://dist.plone.org/versions/zope-2-13-19-versions.cfg
find-links =
    https://dist.plone.org/release/4.2.4
    https://dist.plone.org/thirdparty
extensions =
    mr.developer
#    buildout.dumppickedversions
sources = sources
versions = versions
develop =

[versions]
plone.recipe.zeoserver = 1.3.1
plone.recipe.zope2instance = 4.2.8
five.localsitemanager = 2.0.5
Products.PluginRegistry = 1.3
Products.CMFCore = 2.2.7
Products.GenericSetup = 1.7.3
Products.ZSQLMethods = 2.13.4
zope.interface = 3.6.7
zope.app.publication = 3.12.0
#setuptools = 17.1.1
funcsigs = 0.4
openpyxl = 2.4.0
plone.reload = 2.0.2

[zeo]
recipe = plone.recipe.zeoserver
zeo-address = 127.0.0.1:9100
zeo-var = ${buildout:directory}/var
blob-storage = ${zeo:zeo-var}/blobstorage
#ggs = plone.app.blob

[client1]
recipe = plone.recipe.zope2instance
http-address = 9081
zeo-client = on
zeo-address =  ${zeo:zeo-address}
shared-blob = on
blob-storage =  ${zeo:zeo-var}/blobstorage
user = admin:Slick_RP@21!
products = ${buildout:directory}/matrix_git/prod/
debug-mode = off
verbose-security = off
eggs =
#    pillow
    mysql-python
    simplejson
    haversine
    openpyxl
    requests
    httpagentparser
    ordereddict
    python-memcached
#    python-crontab
#   setuptools
    Products.CMFCore
    Products.ZMySQLDA
#    Products.SQLAlchemyDA
    Products.PluggableAuthService
#    Products.ZopeProfiler
#    Products.MemoryProfiler
#    reportlab
    Products.BeakerSessionDataManager
    collective.fsexternalmethod
    plone.reload
zope-conf-additional =
    extensions ${buildout:directory}/matrix_git/Extensions
    <product-config beaker>
        session.type            file
        session.data_dir        ${buildout:directory}/var/sessions/data
        session.lock_dir        ${buildout:directory}/var/sessions/lock
        session.key             beaker.session
        session.secret          secret
    </product-config>
zcml =
    collective.fsexternalmethod
    plone.reload
event-log-max-size = 5 MB
event-log-old-files = 5
access-log-max-size = 20 MB
access-log-old-files = 10

[client2]
recipe = plone.recipe.zope2instance
http-address = 9082
zeo-client = ${client1:zeo-client}
zeo-address = ${client1:zeo-address}
blob-storage = ${client1:blob-storage}
shared-blob = ${client1:shared-blob}
user = ${client1:user}
products = ${client1:products}
debug-mode = off
verbose-security = off
eggs = ${client1:eggs}
zcml = ${client1:zcml}
zope-conf-additional = ${client1:zope-conf-additional}
event-log-max-size = ${client1:event-log-max-size}
event-log-old-files = ${client1:event-log-old-files}
access-log-max-size = ${client1:access-log-max-size}
access-log-old-files = ${client1:access-log-old-files}

[client3]
recipe = plone.recipe.zope2instance
http-address = 9083
zeo-client = ${client1:zeo-client}
zeo-address = ${client1:zeo-address}
blob-storage = ${client1:blob-storage}
shared-blob = ${client1:shared-blob}
user = ${client1:user}
products = ${client1:products}
debug-mode = off
verbose-security = off
eggs = ${client1:eggs}
zcml = ${client1:zcml}
zope-conf-additional = ${client1:zope-conf-additional}
event-log-max-size = ${client1:event-log-max-size}
event-log-old-files = ${client1:event-log-old-files}
access-log-max-size = ${client1:access-log-max-size}
access-log-old-files = ${client1:access-log-old-files}
[zopepy]
recipe = zc.recipe.egg
eggs = ${client1:eggs}
interpreter = zopepy
scripts = zopepy

[test]
recipe = zc.recipe.testrunner
defaults = ['--auto-color', '--auto-progress']
eggs =
    ${client1:eggs}

[zopeskel]
recipe = zc.recipe.egg
eggs =
    ZopeSkel
    PasteScript

[mysql]
recipe = zest.recipe.mysql
# Note that these urls usually stop working after a while... thanks...
mysql-url = http://downloads.mysql.com/archives/mysql-5.0/mysql-5.0.86.tar.gz
mysql-python-url = http://pypi.python.org/packages/source/M/MySQL-python/MySQL-python-1.2.3.tar.gz

[varnish-build]
recipe = zc.recipe.cmmi
url = ${varnish:download-url}

[varnish]
recipe = plone.recipe.varnish
daemon = ${buildout:parts-directory}/varnish-build/sbin/varnishd
bind = 127.0.0.1:8000
backends = 127.0.0.1:8080
cache-size = 50M

[pidproxy]
recipe = zc.recipe.egg
eggs = supervisor
scripts = pidproxy

[supervisor]
recipe = collective.recipe.supervisor
port = 127.0.0.1:24007
serverurl = http://127.0.0.1:24007
programs =
#    10 mysql      ${buildout:directory}/bin/pidproxy [${buildout:directory}/var/mysql/mysql.pid ${buildout:directory}/parts/mysql/install/bin/mysqld_safe --pid-file=${buildout:directory}/var/mysql/mysql.pid --socket=${buildout:directory}/var/mysql.socket] ${buildout:directory} true
    20 zeo       ${buildout:directory}/bin/zeo [console] ${buildout:directory} true
    30 client1   ${buildout:directory}/bin/client1 [console] ${buildout:directory} true
    40 client2   ${buildout:directory}/bin/client2 [console] ${buildout:directory} true
    50 client3   ${buildout:directory}/bin/client3 [console] ${buildout:directory} true

Solution

  • If you are deploying so frequently, you can either deploy at low traffic times (i.e. at night).

    If the website should be always up, you could have two sets of Plone instances: one set is active and serving requests, the second one is not active.

    When updating, the offline servers are updated and when they are done, a switch is turned (HAProxy for example) to replace the active servers.

    You could even have all servers available always, but for updating, put some offline while they are updated.

    As others, and you as well are pointing, I would never use plone.reload or similar development tools in production.