Как вызвать форму portal_quickinstaller.reinstallProducts за пределами сайта Plone? - PullRequest
4 голосов
/ 28 апреля 2011

У нас работает сервер Zope с большим количеством сайтов Plone (4). Время от времени появляется обновление продукта расширения, которое требует переустановки, чтобы зафиксировать изменения в настройках профиля, например, новые типы контента.

Вручную, это будет означать переход на все сайты Plone portal_quickinstaller, отметку продуктов, пресс-обновление. Это не очень выполнимо, если мы говорим о десятках сайтов, поэтому я пытаюсь автоматизировать это. По сути, до сих пор у меня есть следующие сценарии (Python) в корне Zope:

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 SiteManager, возвращенный zope.component.getSiteManager. Как мне убедить quickinstaller подобрать правильный, то есть тот, что находится на сайте Plone, на котором он живет?

В качестве альтернативы, как бы я пошел по поводу автоматизации переустановки продуктов таким образом, который остается неопределенно возможным для более крупных установок? ( ETA : я знаю, что это не та вещь, которую вы делаете автоматически с помощью cronjob, но, боюсь, обновлений разработанных на месте продуктов нельзя избежать).

Ответы [ 4 ]

8 голосов
/ 28 апреля 2011

Вот как сменить активного локального менеджера сайта. Вы не сможете сделать это в Restricted Python, поэтому вам нужно превратить ваш скрипт Python во внешний метод или в браузер.

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

Вызов setHooks необходимо выполнить только один раз. В Zope 2.12 эти вызовы следует импортировать вместо zope.site.hooks, а в Zope 2.13 - с zope.component.hooks.

Имейте в виду, что вызов reinstallProducts не подходит для всех дополнительных продуктов и не рекомендуется, если вы тщательно не проверили, что делает переустановка, и уверены, что это не вызовет проблем. В некоторых продуктах предусмотрены этапы обновления, которые выполняют действия более избирательно.

4 голосов
/ 28 апреля 2011

Отказ от ответственности : вы уверены, что хотите это сделать?Автоматическая переустановка и обновление продуктов до последней версии, вслепую и без какого-либо тестирования на промежуточном экземпляре, вызывает проблемы.

В любом случае, вы можете сделать это, используя 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 не предназначен для такого использования, и могут быть предостережения . Используйте с осторожностью .

0 голосов
/ 29 апреля 2011

У меня есть этот скрипт на python в корне Zope экземпляра с 7 Plone Sites. Выглядит почти так же, как то, что у вас есть. Возможно, он работает только на этом сайте 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'])
0 голосов
/ 28 апреля 2011

Во-первых, не делайте переустановку, это может сломать ваш сайт во многих случаях.

Далее вы должны учитывать, что надстройки могут предусматривать этап обновления (обычно это так). Используйте API Quickinstaller для достижения этого в PythonScript. Это хорошо, но это также может быть достигнуто с помощью сценария в файловой системе. Проверьте примеры здесь: http://svn.plone.org/svn/plone/plone.org/Products.PloneOrg/trunk/scripts/

Другим решением может быть использование Selenium IDE для записи материала для быстрой установки на одном сайте и копирование результатов этих тестов для запуска на другом сайте (очень странно, не правда ли?)

...