如何在Plone站点外触发portal_quickinstaller.reinstallProducts表单?

时间:2011-04-28 14:11:56

标签: plone zope

我们正在运行一个Zope服务器,最终有大量的Plone(4)站点。不时会出现扩展产品更新,需要重新安装才能获取配置文件设置中的更改,例如新内容类型。

手动,这意味着点击每个Plone网站的portal_quickinstaller,勾选产品,按更新。如果我们谈论几十个网站,这是不太可行的,所以我试图自动化这个。基本上到目前为止,我在Zope根目录中将以下内容作为脚本(Python)生效:

a = context.restrictedTraverse('/')

p = a['Plone']
print p.getSiteManager()
qi = p.restrictedTraverse('portal_quickinstaller')
print qi
qi.reinstallProducts('LinguaPlone')

(简化;实际上我有一个更长的列表而不是单个Plone实例,我可能想要重新安装更长的产品列表。) 这失败了以下内容:

  Module Products.CMFQuickInstallerTool.QuickInstallerTool, line 613, in uninstallProducts
  Module Products.CMFQuickInstallerTool.InstalledProduct, line 272, in uninstall
  Module Products.CMFQuickInstallerTool.InstalledProduct, line 351, in _cascadeRemove
AttributeError: 'BaseGlobalComponents' object has no attribute 'objectItems'

到目前为止,我的调试尝试中,BaseGlobalComponentszope.component.getSiteManager返回的Zope SiteManager。我如何说服quickinstaller选择正确的,即它所居住的Plone网站的那个?

或者,我如何以大型装置仍然模糊可行的方式自动重新安装产品? ( ETA :我知道这不是你用cronjob自动完成的那种事情,但是内部开发产品的更新是无法避免的,我担心。)

4 个答案:

答案 0 :(得分:8)

以下是更改活动本地站点管理器的方法。您将无法在Restricted Python中执行此操作,因此您需要将Python脚本转换为外部方法或浏览器视图。

from zope.app.component.hooks import setHooks, setSite
setHooks()
setSite(site)

setHooks调用只需要完成一次。在Zope 2.12中,应该从zope.site.hooks导入这些调用,而从zope.component.hooks导入Zope 2.13。

请注意,调用reinstallProducts并不适合所有附加产品,除非您仔细检查重新安装的内容并确定不会导致问题,否则不建议这样做。某些产品提供了更有选择性地运行操作的升级步骤。

答案 1 :(得分:4)

免责声明:您确定要这样做吗?自动将产品重新安装和升级到最新版本,盲目地在没有对暂存实例进行任何测试的情况下,就会遇到麻烦。

无论如何,你可以使用XML-RPC和一些调整来做这样的事情。这是使用XML-RPC在实时运行的实例上安装产品的方法:

>>> import xmlrpclib
>>> proxy = xmlrpclib.ServerProxy(
        "http://admin:passwd@localhost:8080/Plone/portal_quickinstaller"
    )
>>> proxy.getProductVersion('Marshall')
'2.0'
>>> proxy.isProductInstalled('Marshall')
'False'
>>> proxy.installProduct('Marshall')
'Registry installed sucessfully.\n'
>>> proxy.isProductInstalled('Marshall')
'True'

要重新安装,您需要子类Products.CMFQuickInstallerTool.QuickInstallerTool.py并为您提供自定义QuickInstallerTool,其方法的关键字参数“重新安装”默认设置为“True”;类似的东西:

442c442
<                        swallowExceptions=None, reinstall=False,
---
>                        swallowExceptions=None, reinstall=True,
452,457c452,457
<         if self.isProductInstalled(p):
<             prod = self._getOb(p)
<             msg = ('This product is already installed, '
<                    'please uninstall before reinstalling it.')
<             prod.log(msg)
<             return msg
---
>         #if self.isProductInstalled(p):
>         #    prod = self._getOb(p)
>         #    msg = ('This product is already installed, '
>         #           'please uninstall before reinstalling it.')
>         #    prod.log(msg)
>         #    return msg

更好:提供自己的方法来收集有关版本的信息并重新安装与XML-RPC协议兼容的产品(因为您无法传递关键字参数)。

可能有更简洁的方法通过XML-RPC执行此操作,但portal_quickinstaller并不意味着以这种方式使用,可能有警告谨慎使用

答案 2 :(得分:0)

首先不要重新安装它可能会在许多情况下破坏您的网站。

接下来,您必须考虑附加组件可能会提供升级步骤(通常他们会这样做)。使用quickinstaller api在PythonScript中实现此目的。这很好,但也可以通过文件系统上的脚本来实现。请查看以下示例:http://svn.plone.org/svn/plone/plone.org/Products.PloneOrg/trunk/scripts/

另一个解决方案可以是使用Selenium IDE在一个站点中记录quickinstaller内容并复制粘贴测试结果以在另一个网站上运行它(非常奇怪不是吗?)

答案 3 :(得分:0)

我在带有7个Plone站点的实例的Zope根目录中获得了这个python脚本。看起来和你的一模一样。它可能只适用于这个Plone 2.5站点(是的,旧的),但我认为它也适用于3.x和4.x.也许一个无辜的看起来差异(我忽略了)导致你的脚本中的错误;也许受限制的你会把它绊倒。 (为清楚起见编辑了脚本。)

SITES = ['site-1', 'site-2']
for site in SITES:
    print "Reinstalling LinguaPlone in %s." % site
    portal = context[site]
    qi = portal.portal_quickinstaller
    qi.reinstallProducts(['LinguaPlone'])