brooklyn-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Alex Heneveld (JIRA)" <>
Subject [jira] [Commented] (BROOKLYN-492) Brooklyn upgrade tricky if using `brooklyn.libraries` for custom OSGi bundles
Date Tue, 02 May 2017 22:55:04 GMT


Alex Heneveld commented on BROOKLYN-492:

The hack workaround suggestion was to have two files claiming identical versions but with
different ranges on the Import-Package so that only the right one can be resolved, avoiding
indeterminacy.  But you are correct Karaf doesn't let you have two installed bundles with
the same name+version so that's out.

But maybe that idea will work with an extra dependency?

Let's say the problem is this:

* Author has a bundle {{my_java:1.0}} which depends on {{brooklyn}} version 0.11, and a catalog
item {{foo}} which requires code in {{my_java}} in package {{org.my_java}}, and this catalog
item is declared in a catalog BOM depending on library {{http:://artifactory/path/to/my_java_1.0.jar}}
* User has deployed an instance of {{foo}} to a brooklyn 0.11 server
* Operator wants to update the brooklyn server to 0.12 -- but {{my_java:1.0}} doesn't work
with 0.12, that bundle won't install, and as a result {{foo}} fails to rebind (or possibly
fails after rebind)

Could a manual workaround be as follows:

# Author creates a new bundle {{my_java_real:1.0}} containing the java currently in {{my_java}},
and ensures that bundle depends on {{brooklyn:[0.11,0.12)}} (e.g. through an imports-package
# Author creates an upgrade to that bundle in {{my_java_real:1.1}} which depends on (and is
compatible with) {{brooklyn:[0.12,0.13)}}
# Author creates a new {{my_java}} which {{Import-Package: org.my_java}} (any version) and
exports the same package
# Author installs this new {{my_java}} at the URL referenced in the BOM -- masking it
# Operator installs both {{my_java_real:1.0}} and {{my_java_real:1.1}} into their brooklyn
container and uninstalls any existing (old) {{my_java}} -- which version of the brooklyn container
doesn't matter and of course one of the {{my_java_real}} versions won't be resolvable but
that's going to be okay
# Operator now rebinds to existing state (possibly a rebind was attempted previously and failed,
but at least it provided an opportunity to install the {{my_java_real}} bundles into their
container; this should pull down the new {{my_java}} which will then resolve the correct {{my_java_real}}

It's a bit tedious, it means manually installing dependency bundles, and swapping the {{my_java}}
URL is ugly but:

* This gives a technique that works with either Brooklyn version
* It doesn't require the *user* to do anything
* It doesn't require doing anything to persisted state

For a v2 of {{foo}} I'd say to put {{foo}} and the BOM into in an OSGi bundle which declares
a {{MANIFEST.MF}} dependency to {{Import-Package: org.my_java}}; this removes the need for
the intermediate {{my_java}} bundle and means Brooklyn doesn't have to track any dependencies
and versions, plus it means we don't need to update {{foo}} on a Brooklyn version change.
 This doesn't solve the problem that we need the appropriate {{my_java_real}} bundle installed,
but there are quite a few options -- simplest is to say to install it into the old version
of Brooklyn, and give an option not to start it (or by default don't start if there is no
{{}} contained inside) -- though in any case it feels like we could live without

There will be times when we _do_ need to update {{foo}} on a Brooklyn version change.  Ideally
there should be a {{foo}} that works with multiple Brooklyn versions so we can install new
{{foo}} into old-version Brooklyn instance, then we have a way to mark old {{foo}} as deprecated,
then upgrade all old {{foo}} instances, then start new Brooklyn version.  But we should think
through the case when {{foo}} _can't_ work with multiple Brooklyn versions; eg {{foo:2}} works
with {{brooklyn:0.12}} and {{foo:3}} with {{brooklyn:0.13}}.  One technique could be to install
{{foo:3}} into the {{brooklyn:0.12}} container but with some sort of "optional" flag so it
doesn't complain if it can't resolve.  We then have a boot-time (or pre-rebind) way when starting
{{brooklyn:0.13}} to say:  "mark {{foo:2}} optional and deprecated, and mark {{foo:3}} not
optional, and upgrade all deprecated things".

I still think the proposal and leaning more on OSGi largely solves things.  I definitely prefer
that over copy-state transformations!

> Brooklyn upgrade tricky if using `brooklyn.libraries` for custom OSGi bundles
> -----------------------------------------------------------------------------
>                 Key: BROOKLYN-492
>                 URL:
>             Project: Brooklyn
>          Issue Type: Bug
>            Reporter: Aled Sage
> When a user refers to their custom OSGi bundle in a catalog's {{brooklyn.libraries}}
section, this could make subsequent upgrade of Brooklyn more difficult.
> This is separate from Alex's email thread to dev@brooklyn "Making blueprint upgrades
easier - feature proposal" (i.e. it would not be solved by Alex's proposal). However, it's
worth thinking about that as well for a long-term holistic solution.
> ---
> Consider the following steps:
> * With Brooklyn 0.11.0:
>   * A user writes a custom OSGi bundle (e.g. containing their own custom policy or Java
entity or whatever), compiled against Brooklyn 0.11.0.
>   * The user creates a catalog item (v1.0), which references that bundle.
>   * The user deploys some apps that use this catalog item (with their state being persisted).
> * When Brooklyn 0.12.0 comes out, the user attempts to upgrade:
>   * The user tries to start 0.12.0, rebinding against their existing persisted state.
This reads the catalog, and thus attempts to install/active the user's custom OSGi bundle.
>   * Their custom bundle may fail to install (e.g. perhaps there are wiring errors due
to dependency changes between 0.11.0 and 0.12.0);
>     or alternatively perhaps the bundle loads, but the instances of the Java policy/entity
fail to be instantiated (e.g. 0.11.0 and 0.12.0 are not binary compatible, with the user's
code relying on some class/method that has changed).
>   * Rebind therefore might fails.
> * The user tries to update their custom OSGi bundle:
>   * The user updates their code and recompiles, to create a v2.0 of their bundle and
of their catalog item.
>   * However, they can't start 0.12.0 with the existing persisted state in order to add
the v2.0 catalog item, and upgrade their entities.
>   * The user might then try starting 0.11.0 up instead, and adding v2.0 of the catalog
item there.  
>     This might work, or it might lead to bundle wiring errors because v2.0 is incompatible
with Brooklyn 0.11.0.
> How likely this is to actually impact a user depends on: 1) what binary incompatible
changes we might make in Brooklyn between versions; and 2) what parts of Brooklyn the user's
Java code makes use of. Some power-users do some pretty sophisticated things, digging into
the less frequented classes of Brooklyn that on first blush might not be considered part of
our "api"!
> ---
> The long-term solution needs a lot more discussion on the dev@brooklyn mailing list.
> However, it might well revolve around being able to start Brooklyn into a usable state,
even when some blueprints/entities have errors. This is important so that errors can be resolved,
and so that errors in some blueprints don't cause the entire server to become unusable.
> This is particularly important for big companies using Brooklyn, where there is a separation
of teams: one team responsible for managing Brooklyn servers/upgrades, and other teams responsible
for writing blueprints / catalog items.
> ---
> A short-term solution could involve using offline tools to transform the persisted state
(e.g. using something like {{bin/brooklyn copy-state ... --transformations ...}}).
> Note that the {{copy-state}} commands are not readily available if one is using just
the Karaf distro of Brooklyn.
> Also note that {{./bin/brooklyn launch --catalogAdd ...}} is also not available if using
the Karaf distro of Brooklyn.

This message was sent by Atlassian JIRA

View raw message