[SOLVED] Remove 'avalable add-ons' from site setup

Is it possible to ‘disable/hide’ add-ons one does not want, but are ‘default’ in Plone. For example: On a classic site I dont want to show ‘plone.volto’ in the control panall ‘add-ons’

The package Plone is a "metapackage" that simply specifies some requirements:

If you don't need all of them do not use pip install Plone

Install only the ones you need. For example:

pip install \
    Products.CMFPlone \
    Products.CMFPlacefulWorkflow \
    plone.app.caching \
    plone.app.iterate \
    plone.app.upgrade \
    plone.restapi \
    -c constraints.txt

Or simply remove the not needed ones (as e.g. Dockerfile.classicui does):

Thanks.
I have a buildout setup, was hoping it was possible to hide some profiles from setuphandlers or some zcml condition.

You can provide a utility that fullfills the INonInstallabe interface with the list of products and profiles that should not be shown in the products control panel.

Check the code that cookieplone creates for that:

https://github.com/plone/cookieplone-templates/blob/main/templates/add-ons/backend/{{%20cookiecutter.__folder_name%20}}/src/packagename/setuphandlers/_init_.py
from Products.CMFPlone.interfaces import INonInstallable
from zope.interface import implementer


@implementer(INonInstallable)
class HiddenProfiles:
    def getNonInstallableProfiles(self):
        """Hide uninstall profile from site-creation and quickinstaller."""
        return [
            "packagename:uninstall",
        ]

    def getNonInstallableProducts(self):
        """Hide the upgrades package from site-creation and quickinstaller."""
        return [
            "packagename.upgrades",
        ]

And:

1 Like

I agree with @erral. This is taken from some code which is running in production.

from Products.CMFPlone.interfaces import INonInstallable
from zope.interface import implementer

@implementer(INonInstallable)
class HiddenProfiles(object):

    def getNonInstallableProfiles(self):
        """Hide uninstall profile from site-creation and quickinstaller."""
        return [
            "my.package:uninstall",
        ]

    def getNonInstallableProducts(self):
        return [
            "ftw.upgrade",
            "pas.plugins.ldap.plonecontrolpanel",
            "plone.app.caching",
            "plone.app.discussion",
            "plone.app.imagecropping",
            "plone.app.iterate",
            "plone.app.multilingual",
            "plone.formwidget.recaptcha",
            "plone.restapi",
            "plone.session",
            "plone.volto",
            "Products.CMFPlacefulWorkflow",
            "Products.membrane",
            "yafowil.plone",
        ]
1 Like

Thanks, works great

1 Like

Note that both plone.api and plone.restapi check for getNonInstallableProducts.

When an addon/product (A) declares an addon/product (B) as "non installable", the "non installable" addon/product (B) won't be installable for any(!) of the sites in the instance, even if the declaring addon/product (A) is not yet installed in a site. Removing/uninstalling the delcaring addon/product (A) won't change that.

Is this expected?

I agree that it would make more sense to only hide them after add-on is installed.

Is it possible to check for ‘hasRunProfile’ or similar before return ?

I would prefer that an add-on (as something that can/should be installed in a site) do not determine how other sites in the instance are installed.

zcml doesn’t have the knowledge of what a site is. But you can add an installer script that fails if the specific site is not allowed.

As it is not mentionned in this thread: having multiple Plone Sites in one Zope Instance, is for larger sites but probably in general not a performant solution.

in the first 10-15 years of Plone and Zope development most of the technical requiremenrts / guard rails like interfaces per site in zcml to isolate view registrations per site and to check for installes profilles have been added. But that it is possible, doesn’t mean its still advisable

One problem I’ve seen with running multiple Plone sites in a Zope instance, is that a more active site seems to use/fill most of the local zodb caches and zope memory.

Also the Catalog objects need to be iin memory first before you can query the Catalog

And For a Plone page to render, you need the Catalog to render navigation, or folder contents.

What we saw happening is that a snall/infrequently visited site could take up to 10-15 seconds for the first incoming page request was served. My theory is that the catalog of that site was no longer in memory or the local caches, so it first has to be loaded again. A few pages with resources are served. And after a while that site Its catalog is pushed out of memory/caches again by a Plone site on the instance with more load/requests.

Zope for object managment only looks at recently used in the whole instance its object tree, i does not distinguish afaik between essential objects to keep then always/preferred available per Plone Instance. Zope does not know about Plone on top of it (unless it is patched/instructed)

Using filesystem cache mechanism /OS swap to page out/in a ‘quiet’ site in a separate Zope instance process, is likely more performant nowadays, than handling it in application specific caches, where the cache in our application is not smart enough.

2 Likes

I totally agree with Fred here.

When we started developing Plone sites, we came from the Zope background (DTML and python scripts) where we could have several sites in a single instance.

When moving to developing with Plone, specially after 2.5, we found out that having several sites per instance created only problems, specially because of the different set of add-ons required per each site.

We never had several Plone sites per instance for production, but we had them for development, and quickly ditched that option because of the mentioned problems.

Thanks for sharing this information. We have been wondering why such delays happen. This might be an explanation.

Interesting bit of background. The ‘push things to the modern OS’ idea I read about in a design article by Paul Henning Kamp (phk) on the Varnish Cache architecture.

I cannot find back the article right now, only an interview that lightly touches it and video interviews with him.

Older caches like Squid had application level caches built in, but this extra layer with the OS also managing memory etc it causes overhead and/or negative interactions when differenr layers try to store/retrieve/swap.

(I should) ask chatgpt to dig up some resources/summary :wink:

1 Like

But this does not depend on the fact to have another site in the same ZODB, if you've raised the cache values enough.

The point is application resource contention vs infrastructure os resource contention. Clearly, the latter is more performant but requires your application to know how infrastructure os works or completely delegate to the infrastructure os.

A solution can be to have the ZODB act as modern system virtualised disk, with a block map instead of jumping around in a file and load everything in memory.

Load the whole/great part of indexes in memory is the problem.

It is like to move your entire archive from the lower floor to the upper floor just to search for something, instead of going to the lower floor and do the search there.

The "catalog load will take time" is because Catalog loads all/most of the indices in memory. But they are btrees like the data in the disk itself!! Use them directly on disk, your VM will get the exact blocks you need from disk instead of loading everything on memory and do it again in your app.

The ZODB cache then will handle the LRU access for peak accesses. A simpler way is to use Lucene like indexes as is instead the ZCatalog indexes (that are ZODB objects, thus they want to solve a problem they're part of!).

Bad caching can be like cheating, seems faster but then it became the bottleneck.