We have spent a great deal of time demonstrating how to use Buildout to develop, deploy, and maintain Plone sites with a wide variety of.
Now we would like to leave you with a clear path to Plone 4, which is likely to be released around the time this book is published.
It is likely that some of the add-ons we have used in this book do not yet have a corresponding Plone 4 compatible release. We will address that as well.
Before we can safely blast off, we must ensure that our buildouts will execute as successfully in the future as they do now.
In this chapter you will learn:
Specifying package versions
Executing Buildout in offline mode
Analyzing our buildout's contents
Staying calm when trouble arises
Upgrading to Plone 4
We have discussed numerous Buildout recipes in this book, but no Buildout extensions (http://pypi.python.org/pypi/zc.buildout#extensions) until now. A Buildout extension is different from a recipe in a few important ways:
Extensions do not define any new sections, whereas recipes are often used within a section (although a section can be defined without a recipe)
Extensions are run after Buildout reads its configuration files, but before it executes them
Extensions are defined within the buildout section
That being said, you do not need to worry too much about the difference; just be aware of which one you are using.
If you know something is an extension, then it should be defined in the
buildout
section. If it is a recipe, it should be defined in its own
section.
We are going to use the buildout.dumppickedversions (http://pypi.python.org/pypi/buildout.dumppickedversions) extension to help us figure out which package's versions are unspecified (which means effectively, we are asking for the latest version).
Logically, we know that versions are unspecified for any package we have added
since we configured Plone 3.3.5's package versions in
buildout.cfg:
[buildout] extends = http://dist.plone.org/release/3.3.5/versions.cfg versions = versions …
You may also recall that we assigned the versions
section
from
http://dist.plone.org/release/3.3.5/versions.cfg to our
buildout's versions
section with versions =
versions
.
Now we are going to add the buildout.dumppickedversions extension to our
buildout
, run Buildout, and examine the output.
In 08-future-dumppicked.cfg
, we have:
[buildout] extends = 07-security-cassandra.cfg extensions = buildout.dumppickedversions
Now run Buildout:
$ bin/buildout -c 08-future-dumppicked.cfg
You should see:
$ bin/buildout -c 08-future-dumppicked.cfg Getting distribution for buildout.dumppickedversions. Got buildout.dumppickedversions 0.4. *************** PICKED VERSIONS **************** [versions] Cheetah = 2.2.1 Paste = 1.7.3.1 Products.CacheSetup = 1.2.1 … #Required by: #PasteScript 1.7.3 PasteDeploy = 1.3.3 #Required by: #ZopeSkel 2.16 PasteScript = 1.7.3 #Required by: #Products.CacheSetup 1.2.1 Products.CMFSquidTool = 1.5.1 … *************** /PICKED VERSIONS ***************
This is incredibly useful information.
Assuming that Buildout is executed successfully, and your Plone site works as
expected, we can now add all of this version information to our
buildout
, and be reasonably confident that it will continue to execute
successfully.
Without a complete and working Known Good Set (KGS), there exists the possibility that a newer package will be released to the Python Package Index that is not compatible with the rest of our KGS.
This would effectively mean one of the two things, the former of which is more likely:
Buildout would fail to complete, citing a version conflict
Buildout would complete, but your Plone site would not start citing a traceback
To avoid this, we use a KGS of packages whenever possible.
Because we specified versions = versions
in
buildout.cfg
, we can add additional versions
blocks
as needed.
In 08-future-versions.cfg
, we have:
[buildout] extends = 08-future-dumppicked.cfg [versions] Cheetah = 2.2.1 Paste = 1.7.3.1 Products.CacheSetup = 1.2.1 … #Required by: #PasteScript 1.7.3 PasteDeploy = 1.3.3 #Required by: #ZopeSkel 2.16 PasteScript = 1.7.3 #Required by: #Products.CacheSetup 1.2.1 Products.CMFSquidTool = 1.5.1 …
Now, run Buildout:
$ bin/buildout -c 08-future-dumppicked.cfg
You should see:
$ bin/buildout -c 08-future-dumppicked.cfg … *************** PICKED VERSIONS **************** [versions] ZopeSkel = 2.16 *************** /PICKED VERSIONS ***************
You will notice that buildout.dumppickedversions no longer picks any versions (except for ZopeSkel, which may be a bug, as version 2.16 is specified).
Specifying package versions is critical to creating a KGS.
So, what happens if the Internet goes down and/or you are unable to reach http://dist.plone.org/release/3.3.5/versions.cfg?
For this, we have two approaches.
The first, newer approach is to use Buildout's extends cache feature, information about which is available on http://pypi.python.org/pypi/zc.buildout#caching-extended-configuration. We will not cover that here, but it is probably worth a look.
In the worst-case scenario though, you can try the following approach.
Inside the code bundle in the versions.cfg
file, we have
included the contents of
http://dist.plone.org/release/3.3.5/versions.cfg.
In the event you lose connectivity, or you want to deploy to an environment sans Internet, you need two things:
The packages themselves (which reside in the eggs
directory)
Their version specifications
We already included version specifications for our add-on packages in
08-future-versions.cfg
, which we discovered with
buildout.dumppickedversions.
Now, we will specify the Plone 3.3.5 package versions in our local
versions.cfg
, rather than the versions.cfg
file
located on
http://dist.plone.org/release/3.3.5/versions.cfg. In
buildout.cfg
, we have:
[buildout] extends = http://dist.plone.org/release/3.3.5/versions.cfg versions = versions …
If you add a comment (#) to the beginning of the second line and then add
extends = versions.cfg
below that, you will have this:
[buildout] #extends = http://dist.plone.org/release/3.3.5/versions.cfg extends = versions.cfg versions = versions …
Now execute the last known good configuration with the -o
option to indicate offline mode.
You should see:
$ bin/buildout -o -c 08-future-versions.cfg Updating zope2. Updating fake eggs Updating instance. Updating omelette. … Updating zopepy. Updating zopeskel. Updating zeo. Updating backup. Updating cron. Updating cron2. Updating varnish-install. Updating varnish. Updating squid-install. Updating squid. Updating env. Updating instance1. Updating instance2. Updating haproxy-install. Updating haproxy-config. Updating pound-install. Updating pound-config. Updating supervisor. Updating munin. …
In this book, we have created a fairly large buildout, spread across many files. As a result, perhaps you are wondering what it would look like if the same buildout were contained in a single file?
We answer that question in 08-future-final.cfg
, which contains
the following sections, parameters, and values, presented here along with some
commentary about each:
Every buildout must define a buildout
section:
[buildout]
By assigning parameters from various versions
sections
to the versions
parameter in the
buildout
section, we are able to specify package version
numbers:
versions = versions
Every buildout
section must have a
parts
parameter (even if it is empty):
parts = zope2 instance
In Chapter 2, Site
Basics, we introduced the collective.recipe.plonesite recipe
(http://pypi.python.org/pypi/collective.recipe.plonesite) configured in a
section called plonesite:
# Chapter 2 plonesite
In Chapter 3, Appearance,
we introduced the collective.recipe.omelette recipe
(http://pypi.python.org/pypi/collective.recipe.omelette) configured in a
section called omelette
. We also demonstrated the use of
the zc.recipe.egg recipe (http://pypi.python.org/pypi/zc.recipe.egg) in
the zopepy
and zopeskel
sections:
# Chapter 3 omelette zopepy zopeskel
In Chapter 5, Deployment and Maintenance, we introduced the collective.recipe.backup recipe (http://pypi.python.org/pypi/collective.recipe.backup) to generate scripts to back up your Plone site's database and also introduced the z3c.recipe.usercrontab recipe (http://pypi.python.org/pypi/z3c.recipe.usercrontab) to automate the execution of these scripts.
We also discussed using the plone.recipe.zope2zeoserver recipe (http://pypi.python.org/pypi/plone.recipe.zope2zeoserver) to configure a ZEO server:
# Chapter 5 backup cron cron2 zeo
In Chapter 6, Optimization, for the purpose of site optimization, we demonstrated the use of the collective.recipe.supervisor (http://pypi.python.org/pypi/collective.recipe.supervisor), collective.recipe.template (http://pypi.python.org/pypi/collective.recipe.template), hexagonit.recipe.cmmi (http://pypi.python.org/pypi/hexagonit.recipe.cmmi), plone.recipe.haproxy (http://pypi.python.org/pypi/plone.recipe.haproxy), plone.recipe.squid (http://pypi.python.org/pypi/plone.recipe.squid), plone.recipe.varnish (http://pypi.python.org/pypi/plone.recipe.varnish), zc.recipe.cmmi (http://pypi.python.org/pypi/zc.recipe.cmmi), and zc.recipe.egg recipes within the following sections.
# Chapter 6 instance1 instance2 haproxy-install haproxy-config pound-install pound-config munin squid-install squid varnish-install varnish supervisor
We also demonstrated the use of Buildout macros.
In Chapter 7, Security, we demonstrated the use of the gocept.recipe.env recipe (http://pypi.python.org/pypi/gocept.recipe.env) to configure the Zope 2 effective user dynamically:
# Chapter 7 env
In Chapter 3, we demonstrated how to add a ZopeSkel-generated (http://pypi.python.org/pypi/ZopeSkel) theme package to your buildout:
# Chapter 3 develop = src/my.theme
In this chapter, we demonstrated how to get a list of packages whose versions have not been specified, by using the buildout.dumppickedversions Buildout extension (http://pypi.python.org/pypi/buildout.dumppickedversions):
# Chapter 8 extensions = buildout.dumppickedversions
In Chapter 2, we introduced the Plone buildout (in
buildout.cfg)
, which uses the plone.recipe.zope2install
(http://pypi.python.org/pypi/plone.recipe.zope2install) and
plone.recipe.zope2instance
(http://pypi.python.org/pypi/plone.recipe.zope2instance) recipes to install
Zope 2 and configure a Zope 2 instance, respectively:
[zope2] recipe = plone.recipe.zope2install url = ${versions:zope2-url} [instance] recipe = plone.recipe.zope2instance zope2-location = ${zope2:location} user = admin:admin eggs = Plone
In Chapter 2, for the purpose of site theming, we added the following
packages to the eggs
parameter of the
instance
section:
# Chapter 2 Products.Scrawl webcouturier.dropdownmenu collective.portlet.explore collective.portlet.sitemap
In Chapter 3, we created and demonstrated the use of a very simple theme package on the filesystem:
# Chapter 3 my.theme
In Chapter 3, we installed an attractive add-on theme package:
# Chapter 3 beyondskins.ploneday.site2010
In Chapter 4, Administration, we demonstrated user and group management with LDAP, as well as how to configure Zope 2 to send a mail to the terminal:
# Chapter 4 plone.app.ldap # Products.PrintingMailHost
In Chapter 5, we demonstrated how to rotate Zope 2 log files with iw.rotatezlogs (http://pypi.python.org/pypi/iw.rotatezlogs):
# Chapter 5 iw.rotatezlogs
In Chapter 6, we demonstrated how to configure various cache-related settings easily with the CacheFu (http://pypi.python.org/pypi/Products.CacheSetup) add-on. We also demonstrated how to produce useful site monitoring graphs with munin.zope (http://pypi.python.org/pypi/munin.zope) and Munin:
# Chapter 6 Products.CacheSetup munin.zope
In Chapter 7, we demonstrated how to perform a local roles audit with Cassandra (http://pypi.python.org/pypi/zopyx.plone.cassandra):
# Chapter 7 zopyx.plone.cassandra
In the various chapters, we explained the need to configure the
zcml
parameter in the instance
section:
zcml = # Chapter 2 webcouturier.dropdownmenu collective.portlet.explore collective.portlet.sitemap # Chapter 3 beyondskins.ploneday.site2010 # Chapter 4 plone.app.ldap # Chapter 6 munin.zope # Chapter 7 zopyx.plone.cassandra
Once we added the iw.rotatezlogs package to the eggs
parameter of the instance
section, we added these
parameters to the instance
section (which configure
additional settings in the zope.conf
file):
# Chapter 5 zeo-client = True event-log-custom = %import iw.rotatezlogs <rotatelogfile> path ${buildout:directory}/var/log/instance.log max-bytes 1MB backup-count 5 </rotatelogfile> access-log-custom = %import iw.rotatezlogs <rotatelogfile> path ${buildout:directory}/var/log/instance-Z2.log max-bytes 1MB backup-count 5 </rotatelogfile>
The plonesite
section adds and configures a Plone site
in the database whenever Buildout runs:
# Chapter 2 [plonesite] recipe = collective.recipe.plonesite site-id = Plone
The omelette
section creates symbolic links from
the parts/omelette
directory to various packages
elsewhere on the filesystem:
# Chapter 3 [omelette] recipe = collective.recipe.omelette eggs = ${instance:eggs} packages = ${zope2:location}/lib/python
The zopepy
section creates a
bin/zopepy
script (Python interpreter) with the instance
packages and Zope 2 libraries added to
sys.path:
[zopepy] recipe = zc.recipe.egg eggs = ${instance:eggs} interpreter = zopepy extra-paths = ${zope2:location}/lib/python scripts = zopepy
The zopeskel
section installs ZopeSkel in the
buildout:
[zopeskel] recipe = zc.recipe.egg dependent-scripts = true
The backup, cron
, and cron2
sections
create backup scripts and cron
entries for the purpose of
performing backups:
# Chapter 5 [backup] recipe = collective.recipe.backup [cron] recipe = z3c.recipe.usercrontab command = ${buildout:directory}/bin/backup times = 0 0 * * * [cron2] recipe = z3c.recipe.usercrontab command = ${buildout:directory}/bin/zeopack times = 0 0 1 * *
The zeo
section installs a ZEO instance:
[zeo] recipe = plone.recipe.zope2zeoserver zope2-location = ${zope2:location} eggs = ${instance:eggs} zeo-log-custom = %import iw.rotatezlogs <rotatelogfile> path ${buildout:directory}/var/log/zeo.log max-bytes 1MB backup-count 5 </rotatelogfile>
The haproxy-config
section uses the
collective.recipe.template recipe to generate a template for HAProxy
dynamically, based on the contents of an input template:
# Chapter 6 [haproxy-config] recipe = collective.recipe.template input = ${buildout:directory}/templates/haproxy.cfg.in output = ${buildout:directory}/etc/haproxy.cfg
The haproxy-install
section downloads and installs
HAProxy (which unfortunately cannot be compiled with any of the available
CMMI recipes (such as zc.recipe.cmmi) as you may expect it to be):
[haproxy-install] recipe = plone.recipe.haproxy
The instance1
and instance2
sections demonstrate the use of Buildout macros to easily create
duplicate instances based on the instance
section, with
various parameters changed or added as needed:
[instance1] < = instance http-address = 8081 # Chapter 7 effective-user = ${env:USER} http-address = 127.0.0.1:8081 [instance2] < = instance http-address = 8082 # Chapter 7 effective-user = ${env:USER} http-address = 127.0.0.1:8082
The munin
section configures a
bin/munin
script that is used to generate symbolic links from
your site's Munin plugins directory to bin/munin
(which in turn, produces appropriate output for Munin, based on how it is
invoked, that is with the various symbol links).
[munin] recipe = zc.recipe.egg eggs = munin.zope arguments = http_address=${instance1:http-address}, user=${instance1:user}
The pound-config
section uses the
collective.recipe.template recipe to generate a template for Pound
dynamically based on the contents of an input template:
[pound-config] recipe = collective.recipe.template input = ${buildout:directory}/templates/pound.cfg.in output = ${buildout:directory}/etc/pound.cfg
The pound-install
section uses the
hexagonit.recipe.cmmi recipe to download and install Pound:
[pound-install] recipe = hexagonit.recipe.cmmi url = http://www.apsis.ch/pound/Pound-2.4.5.tgz make-targets = keep-compile-dir = true
The squid-install
section uses the zc.recipe.cmmi
recipe to download and install Squid:
[squid-install] recipe = zc.recipe.cmmi url = http://www.squid-cache.org/Versions/v2/2.7/squid-2.7.STABLE9.tar.gz
The squid
section uses the plone.recipe.squid recipe to
configure a Squid configuration file:
[squid] recipe = plone.recipe.squid:instance cache-size = 1000 daemon = ${squid-install:location}/sbin/squid backends = 127.0.0.1:8080 bind = 127.0.0.1:3128
The following sections provide friendly variable names to access some unfriendly in-length parameters:
[pound] directory = ${buildout:directory}/parts/pound-install__compile__ config = ${pound:directory}/etc/pound.cfg [haproxy] config = ${buildout:directory}/etc/haproxy.cfg
The supervisor
section configures Supervisor to
execute and control all the services in our buildout:
[supervisor] recipe = collective.recipe.supervisor programs = #Prio Name Program Params 00 zeo ${zeo:location}/bin/runzeo 00 instance1 ${instance1:location}/bin/runzope 00 instance2 ${instance2:location}/bin/runzope 00 haproxy ${buildout:directory}/bin/haproxy [-f ${haproxy:config} ] 00 pound ${pound:directory}/Pound-2.4.5/pound [-f ${pound:config} ] 00 varnish ${buildout:directory}/bin/varnish [-F] 00 squid ${buildout:directory}/bin/squid [-N]
The varnish-install
section uses the zc.recipe.cmmi
recipe to download and install Varnish:
[varnish-install] recipe = zc.recipe.cmmi url = http://downloads.sourceforge.net/project/varnish/varnish/ 2.1.2/varnish-2.1.2.tar.gz
The varnish
section uses the plone.recipe.varnish
recipe to create a Varnish configuration file:
[varnish] recipe = plone.recipe.varnish daemon = ${varnish-install:location}/sbin/varnishd
The env
section provides access to the operating
system shell's environment variables (for example, USER):
[env] recipe = gocept.recipe.env
The hosts
and ports
sections provide
a way to standardize and easily control IP address and port
settings:
# Chapter 7 [hosts] localhost = 127.0.0.1 [ports] instance1 = 8081 instance2 = 8082
In this chapter, we discussed how to configure package versions in part,
by specifying version numbers in a versions
section
(and also by setting versions = versions
in the
buildout
section):
# Chapter 8 [versions] Cheetah = 2.2.1 Paste = 1.7.3.1 Products.CacheSetup = 1.2.1 … #Required by: #PasteScript 1.7.3 PasteDeploy = 1.3.3 #Required by: #ZopeSkel 2.16 PasteScript = 1.7.3 #Required by: #Products.CacheSetup 1.2.1 Products.CMFSquidTool = 1.5.1 … # Buildout infrastructure plone.recipe.zope2install = 3.2 plone.recipe.zope2instance = 3.6 plone.recipe.zope2zeoserver = 1.4 setuptools = 0.6c11 zc.buildout = 1.4.3 zc.recipe.egg = 1.2.2 # Zope zope2-url = http://www.zope.org/Products/Zope/2.10.11/Zope-2.10.11-final.tgz # External dependencies Markdown = 1.7 PIL = 1.1.6 elementtree = 1.2.7-20070827-preview feedparser = 4.1 python-openid = 2.2.4 simplejson = 2.0.9 # Plone release Plone = 3.3.5 Products.ATContentTypes = 1.3.4 Products.ATReferenceBrowserWidget = 2.0.5 …
For whatever it is worth, this is the final buildout example (before we blast off in to the future) that demonstrates all the functionality we have added incrementally with each chapter.
Ideally, you can browse through 08-future-final.cfg
and when
you see something you do not understand, refer to the corresponding chapter for an
explanation.
It is a harsh reality that while experimenting with your Plone buildout (such as adding various packages from the Python Package Index), things are more likely to go wrong than they are to go right.
Do yourself a favor and:
Do not panic.
Paste the error message to http://paste.plone.org.
Join the #plone IRC channel on http://irc.freenode.net/ and ask the folks in there if they understand the error.
Alternatively, ask a question on the Plone users' mailing list on Sourceforge.net (https://lists.sourceforge.net/lists/listinfo/plone-users).
A lot of times, what appears to be a cryptic error is actually not to the trained eye. It is important that you learn to tell the difference.
You can read more about the available support options for Plone on http://plone.org/support.
The Plone community is a thoughtful and generous one, so you will be welcomed and encouraged to learn!
It is now time to explore upgrading to Plone 4.
Nowadays, as far as the software itself is concerned, this is a relatively simple process.
Especially as far as our buildout.cfg
file is concerned, it is
simple.
At the time of this writing, Plone 4 is just about to release its first release candidate. This means that we can experiment with the most recent beta release beta 3.
For Plone 4 beta 3's versions.cfg file, visit http://dist.plone.org/release/4.0b3/versions.cfg.
Even though we have already specified a versions.cfg
, we can
specify another one, because Buildout will just use the last specified value for
each parameter.
In the case of a versions
section that looks like as shown,
Buildout will use the latter version:
[versions] Plone = 3.3.5 Plone = 4.0b3
Effectively, extending the Plone 4 beta 3 versions.cfg
file and
executing Buildout upgrades your software stack (but not your database) to Plone 4
beta 3.
There are a few additional concerns we must address before you do that.
First, and most importantly, you must re-bootstrap your buildout with Python 2.6, as shown:
$ python2.6 bootstrap.py
Second, you must backup your database (which you learned how to do in Chapter 5).
Third, you must uninstall the add-ons for which there is no Plone 4 compatible release. In our case, we must uninstall all the add-ons (more or less).
Fourth, you will browse to
http://localhost:8080/Plone
, click on
Site Setup | Add-on
Products and uninstall all the add-ons we had
installed.
Ideally, this process will be trouble-free, though often it is not. In the event you have trouble uninstalling an add-on, you should contact the author.
Fifth, we are going to subtract all the sections and parameters that
are not absolutely essential to run Plone 4, from our buildout. That means
everything but the instance
section is to be
subtracted.
Finally, you will execute the buildout.
In 08-future-plone4.cfg
we have:
[buildout] extends = 08-future-final.cfg http://dist.plone.org/release/4.0b3/versions.cfg develop = parts -= zope2 omelette zopepy zopeskel backup cron cron2 zeo instance1 instance2 haproxy-install haproxy-config pound-install pound-config munin squid-install squid varnish-install varnish supervisor [instance] zope2-location = eggs -= Products.Scrawl webcouturier.dropdownmenu collective.portlet.explore collective.portlet.sitemap my.theme beyondskins.ploneday.site2010 plone.app.ldap iw.rotatezlogs Products.CacheSetup munin.zope zopyx.plone.cassandra event-log-custom = access-log-custom = zeo-client =
Now run Buildout:
$ bin/buildout c 08-future-plone4.cfg
This Buildout should complete successfully. However, in the real world you do not have to go to the trouble of subtracting out all the Plone 3 parts of your buildout. You can just use a real Plone 4 buildout.
In 08-future-just-plone4.cfg
, we have:
[buildout] extends = http://dist.plone.org/release/4.0b3/versions.cfg versions = versions parts = instance [instance] recipe = plone.recipe.zope2instance user = admin:admin eggs = Plone
Now run Buildout:
$ bin/buildout c 08-future-just-plone4.cfg
You should see:
Installing instance. Generated script /Users/aclark/Developer/plone-site-admin/buildout/bin/instance.
Start Plone:
$ bin/instance fg
You should see:
$ bin/instance fg 2010-05-24 22:42:24 INFO ZServer HTTP server started at Mon May 24 22:42:24 2010 Hostname: localhost Port: 8080 2010-05-24 22:42:27 INFO ZODB.blob (31597) Blob directory `/Users/aclark/Developer/plone-site-admin/buildout/var/blobstorage` is unused and has no layout marker set. Selected `bushy` layout. 2010-05-24 22:42:27 INFO ZODB.blob (31597) Blob temporary directory /Users/aclark/Developer/plone-site-admin/buildout/var/blobstorage/tmp does not exist. Created new directory. 2010-05-24 22:42:27 WARNING ZODB.blob (31597) Blob dir /Users/aclark/Developer/plone-site-admin/buildout/var/blobstorage/ has insecure mode setting /Users/aclark/Developer/eggs/Zope2-2.12.5-py2.6-macosx-10.6-x86_64.egg/Zope2/App/ClassFactory.py:22: DeprecationWarning: PlacelessTranslationService: The PlacelessTranslationService itself is deprecated and will be removed in the next major version of PTS. return getattr(m, name) 2010-05-24 22:42:31 WARNING OFS.Uninstalled Could not import class TextIndex from module Products.PluginIndexes.TextIndex.TextIndex /Users/aclark/Developer/eggs/Zope2-2.12.5-py2.6-macosx-10.6-x86_64.egg/Zope2/App/ClassFactory.py:22: DeprecationWarning: BrokenMessageCatalog: PlacelessTranslationServices implementation of Message catalogs and the MoFileCache is deprecated and will be removed in the next major version of PTS. /Users/aclark/Developer/eggs/Zope2-2.12.5-py2.6-macosx-10.6-x86_64.egg/Zope2/App/ClassFactory.py:22: DeprecationWarning: BrokenMessageCatalog: PlacelessTranslationServices implementation of Message catalogs and the MoFileCache is deprecated and will be removed in the next major version of PTS. return getattr(m, name) 2010-05-24 22:42:32 INFO Zope Ready to handle requests
Browse to http://localhost:8080/
(not
http://localhost:8080/Plone
).
You should see:
In this final chapter, you have learned:
How to specify package versions, with help from a Buildout extension
How to execute Buildout successfully when no Internet connection is available
How to create and manage a complex buildout in one or many files
How to upgrade Plone and manage the complexities of the process
What to do when errors occur
In this book, you have hopefully learned how to manage your Plone site using Buildout and related tools. Your potential to build attractive, multi-functional websites with Plone is limitless.
Assembling Plone applications with Buildout is a complex task, but one that can be managed effectively without too much complexity.
The author hopes you have enjoyed reading this book, and wishes you all the best with your Plone sites!
3.149.228.138