我们正在运行一个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'
到目前为止,我的调试尝试中,BaseGlobalComponents
是zope.component.getSiteManager
返回的Zope SiteManager。我如何说服quickinstaller选择正确的,即它所居住的Plone网站的那个?
或者,我如何以大型装置仍然模糊可行的方式自动重新安装产品? ( ETA :我知道这不是你用cronjob自动完成的那种事情,但是内部开发产品的更新是无法避免的,我担心。)
答案 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'])