Merge lp:~thedac/charms/precise/postgresql/package-holding into lp:charms/postgresql

Proposed by David Ames
Status: Merged
Merged at revision: 95
Proposed branch: lp:~thedac/charms/precise/postgresql/package-holding
Merge into: lp:charms/postgresql
Diff against target: 65 lines (+24/-1)
3 files modified
config.yaml (+6/-0)
hooks/hooks.py (+17/-0)
templates/pg_hba.conf.tmpl (+1/-1)
To merge this branch: bzr merge lp:~thedac/charms/precise/postgresql/package-holding
Reviewer Review Type Date Requested Status
Stuart Bishop (community) Approve
Review via email: mp+216411@code.launchpad.net

Description of the change

Allow the postgresql-$VERSION package to be held in production environments
Revert back to correct use of md5 for nagios check via pgpass

To post a comment you must log in.
Revision history for this message
Stuart Bishop (stub) wrote :

An alternative approach is to dump the 'need_upgrade' logic in update_repos_and_packages(), and the charm should never attempt to upgrade the package (we already filter out already installed packages from the list of packages we punt to fetch.apt_install()). If this meets your concerns, it would be my preferred approach as discussions on the juju mailing list recently make me think that package upgrades is not the responsibility of the charm as it just can't be done well there (no hook is fired if a new security update is published in the archive). We have other solutions such as Landscape and automated security package installation for this.

If we need to keep this approach, it would be nice to validate the value of the new config item in validate_config(), since we don't have true enum support. If other charms would find it useful, consider shoving it in charm-helpers or perhaps a subordinate charm.

We should have a test for the nagios connection to ensure we don't break it again. https://code.launchpad.net/~stub/charms/precise/postgresql/fix-failover-tests/+merge/214316 has all the work to make this trivial in test.py (deploy relevant services and relations, introspect the relation settings for credentials, open a database connection via a SSH tunnel to confirm those credentials work from that unit). If you don't want to rebase from my branch and add the test, please open a bug so it doesn't get lost and I'll add one soon.

Revision history for this message
Stuart Bishop (stub) wrote :

Also, if we keep this approach , the call to ensure_package_status() should probably go in update_repos_and_packages() rather than config_changed(). This encapsulates all the apt stuff better, and will stop update_repos_and_packages() upgrading your packages before you get a chance to set the hold/install flag. At the moment, I think if you set the config item on an existing service then the packages will get upgraded before the hold takes effect.

review: Needs Fixing
Revision history for this message
James Troup (elmo) wrote :

Stuart Bishop <email address hidden> writes:

> An alternative approach is to dump the 'need_upgrade' logic in
> update_repos_and_packages(), and the charm should never attempt to
> upgrade the package (we already filter out already installed
> packages from the list of packages we punt to
> fetch.apt_install()). If this meets your concerns, it would be my
> preferred approach as discussions on the juju mailing list recently
> make me think that package upgrades is not the responsibility of the
> charm as it just can't be done well there (no hook is fired if a new
> security update is published in the archive). We have other
> solutions such as Landscape and automated security package
> installation for this.

So, to be clear this is not about trying to handle upgrades within the
charm. What we're trying to do is prevent a Landscape auto-upgrade
profile from upgrading postgres and taking down a production service
as a result). Landscape will respect package holds, so it seems like
(being able to) set package holds within the charm is the logical
place to do so.

--
James

Revision history for this message
Stuart Bishop (stub) wrote :

On 18 April 2014 22:51, James Troup <email address hidden> wrote:

> So, to be clear this is not about trying to handle upgrades within the
> charm. What we're trying to do is prevent a Landscape auto-upgrade
> profile from upgrading postgres and taking down a production service
> as a result). Landscape will respect package holds, so it seems like
> (being able to) set package holds within the charm is the logical
> place to do so.

This makes me wonder if it would be better to add a list of held
packages to the Landscape subordinate charm where all services can
make use of it. This would be a little awkward, as it requires the
operator to specify the primary PostgreSQL package name, whereas the
PostgreSQL charm knows the package name to hold.

(I'm not blocking on any of this - worst case is we document the
feature as experimental if we are not sure we want to support it in
its current form)

--
Stuart Bishop <email address hidden>

Revision history for this message
David Ames (thedac) wrote :

> An alternative approach is to dump the 'need_upgrade' logic in
> update_repos_and_packages(), and the charm should never attempt to upgrade the
> package (we already filter out already installed packages from the list of
> packages we punt to fetch.apt_install()). If this meets your concerns, it
> would be my preferred approach as discussions on the juju mailing list
> recently make me think that package upgrades is not the responsibility of the
> charm as it just can't be done well there (no hook is fired if a new security
> update is published in the archive). We have other solutions such as Landscape
> and automated security package installation for this.

I agree we should dump the need_upgrade logic as the charm should not be responsible for upgrading. However, the intent is to hold the packge such that landscape or other update services will also not upgrade postgresql (if held) in a production environment. This is standard for us in other charms.

> If we need to keep this approach, it would be nice to validate the value of
> the new config item in validate_config(), since we don't have true enum
> support. If other charms would find it useful, consider shoving it in charm-
> helpers or perhaps a subordinate charm.

Will do the validate_config().
We should look into adding this to charm-helpers.

> We should have a test for the nagios connection to ensure we don't break it
> again. https://code.launchpad.net/~stub/charms/precise/postgresql/fix-
> failover-tests/+merge/214316 has all the work to make this trivial in test.py
> (deploy relevant services and relations, introspect the relation settings for
> credentials, open a database connection via a SSH tunnel to confirm those
> credentials work from that unit). If you don't want to rebase from my branch
> and add the test, please open a bug so it doesn't get lost and I'll add one
> soon.

We should look at this as well.

> Also, if we keep this approach , the call to ensure_package_status() should
> probably go in update_repos_and_packages() rather than config_changed(). This
> encapsulates all the apt stuff better, and will stop
> update_repos_and_packages() upgrading your packages before you get a chance to
> set the hold/install flag. At the moment, I think if you set the config item
> on an existing service then the packages will get upgraded before the hold
> takes effect.

Initial testing having this in update_repos_and_packages() there is a bit of a chicken and egg problem. If the package is held before it is installed apt complains. We need to explore a robust solution for this.

I have created RT#69634 to track this process.

93. By David Ames

Use validate_config, move ensure_package_status to update_repos_and_packages(), handle when postgres not yet installed

Revision history for this message
David Ames (thedac) wrote :

> On 18 April 2014 22:51, James Troup <email address hidden> wrote:
>
> > So, to be clear this is not about trying to handle upgrades within the
> > charm. What we're trying to do is prevent a Landscape auto-upgrade
> > profile from upgrading postgres and taking down a production service
> > as a result). Landscape will respect package holds, so it seems like
> > (being able to) set package holds within the charm is the logical
> > place to do so.
>
> This makes me wonder if it would be better to add a list of held
> packages to the Landscape subordinate charm where all services can
> make use of it. This would be a little awkward, as it requires the
> operator to specify the primary PostgreSQL package name, whereas the
> PostgreSQL charm knows the package name to hold.
>
> (I'm not blocking on any of this - worst case is we document the
> feature as experimental if we are not sure we want to support it in
> its current form)

So again, this is pretty standard for IS charms (apache, haproxy, canonical-is-charms/postgresql) and we are just trying to bring postgres up to that standard.

I have

Check pagack_state with validate_config
Moved ensure_package_status to update_repos_and_packages()
Handled when postgres is not yet installed

Please take another look

Revision history for this message
Stuart Bishop (stub) wrote :

> I have
>
> Check pagack_state with validate_config
> Moved ensure_package_status to update_repos_and_packages()
> Handled when postgres is not yet installed
>
> Please take another look

Please change the bare except to 'except subprocess.CalledProcessError'. Bare excepts are always bugs, since they catch ugly exceptions you have no hope of handling correctly.

Please open a bug for adding the nagios connection test. Please open a bug for testing this new held package behavior. The charm is complex enough that features without tests will be broken. I'm happy to add the tests.

Otherwise, good to go.

review: Approve
Revision history for this message
Stuart Bishop (stub) wrote :

IF you would rather avoid the run() call to dpkg entirely, I think you will be able to tell if the postgresql package is installed by looking at the filtered list of packages to install.

packages = fetch.filter_installed_packages(packages)

At this point, I think charm helpers has removed any packages already installed, so if postgresql-x.x is not in the list you are good to hold/unhold it.

94. By David Ames

Use filtered package list to determine if postgres is installed

Revision history for this message
UCI Engine Bot (ue-uci-engine) wrote :

Used filtered package list. Please do final review and merge.

Bugs filed:
https://bugs.launchpad.net/charms/+bug/1316361
https://bugs.launchpad.net/charms/+bug/1316362

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'config.yaml'
2--- config.yaml 2014-04-04 12:05:49 +0000
3+++ config.yaml 2014-05-06 00:01:34 +0000
4@@ -432,3 +432,9 @@
5 type: string
6 default: ""
7 description: EXPERIMENTAL. OpenStack Swift tenant name.
8+ package_status:
9+ default: "install"
10+ type: string
11+ description: |
12+ The status of service-affecting packages will be set to this value in the dpkg database.
13+ Useful valid values are "install" and "hold".
14
15=== modified file 'hooks/hooks.py'
16--- hooks/hooks.py 2014-04-28 13:49:07 +0000
17+++ hooks/hooks.py 2014-05-06 00:01:34 +0000
18@@ -866,10 +866,23 @@
19 local_state[name] = config_data.get(name, None)
20 local_state.save()
21
22+ package_status = config_data['package_status']
23+ if package_status not in ['install', 'hold']:
24+ valid = False
25+ log("package_status must be 'install' or 'hold' not '{}'"
26+ "".format(package_status), CRITICAL)
27+
28 if not valid:
29 sys.exit(99)
30
31
32+def ensure_package_status(package, status):
33+ selections = ''.join(['{} {}\n'.format(package, status)])
34+ dpkg = subprocess.Popen(['dpkg', '--set-selections'],
35+ stdin=subprocess.PIPE)
36+ dpkg.communicate(input=selections)
37+
38+
39 #------------------------------------------------------------------------------
40 # Core logic for permanent storage changes:
41 # NOTE the only 2 "True" return points:
42@@ -1584,6 +1597,10 @@
43 packages.append('pgtune')
44 packages.extend((hookenv.config('extra-packages') or '').split())
45 packages = fetch.filter_installed_packages(packages)
46+ # Set package state for main postgresql package if installed
47+ if 'postgresql-{}'.format(version) not in packages:
48+ ensure_package_status('postgresql-{}'.format(version),
49+ hookenv.config('package_status'))
50 fetch.apt_install(packages, fatal=True)
51
52
53
54=== modified file 'templates/pg_hba.conf.tmpl'
55--- templates/pg_hba.conf.tmpl 2014-03-04 21:50:06 +0000
56+++ templates/pg_hba.conf.tmpl 2014-05-06 00:01:34 +0000
57@@ -5,7 +5,7 @@
58 # Database administrative login by UNIX sockets
59 local all root,postgres ident map=superusers
60 local replication root,postgres ident map=superusers
61-local all nagios ident
62+local all nagios md5
63
64 {% if access_list is defined -%}
65 {% for unit in access_list -%}

Subscribers

People subscribed via source and target branches