Merge lp:~ajkavanagh/charms/trusty/keystone/add-service-checks-lp1524388 into lp:~openstack-charmers-archive/charms/trusty/keystone/next

Proposed by Alex Kavanagh
Status: Merged
Merged at revision: 209
Proposed branch: lp:~ajkavanagh/charms/trusty/keystone/add-service-checks-lp1524388
Merge into: lp:~openstack-charmers-archive/charms/trusty/keystone/next
Diff against target: 220 lines (+109/-5)
6 files modified
charmhelpers/contrib/network/ip.py (+15/-0)
charmhelpers/contrib/openstack/context.py (+5/-1)
charmhelpers/contrib/openstack/templates/section-keystone-authtoken (+11/-0)
charmhelpers/contrib/openstack/utils.py (+73/-2)
hooks/keystone_utils.py (+2/-1)
unit_tests/test_keystone_utils.py (+3/-1)
To merge this branch: bzr merge lp:~ajkavanagh/charms/trusty/keystone/add-service-checks-lp1524388
Reviewer Review Type Date Requested Status
David Ames (community) Approve
Review via email: mp+285608@code.launchpad.net

Description of the change

For review/comments only:

  Synced in lp:~ajkavanagh/charm-helpers/add-service-checks-lp1524388 version
  of charm-helpers to test that modification will work - this is for demo
  purposes only and will be revised prior to merge proposal.

  The modified version of charm-helpers actually checks if the service is running
  and listening on any ports specified. This change to keystone adds the service
  and port checks as part of assess_status().

  Also changed tests to to work with revision 514:
  "misc changes for haproxy template and context ..."
  which required changes to the test_haproxy_context_service_enabled test

To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #386 keystone-next for ajkavanagh mp285608
    LINT OK: passed

Build: http://10.245.162.36:8080/job/charm_lint_check/386/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #307 keystone-next for ajkavanagh mp285608
    UNIT OK: passed

Build: http://10.245.162.36:8080/job/charm_unit_test/307/

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

This looks great. And will be ready to merge after two more steps.

One, we have some text conflicts that need to be resolved.

Two, my manual run of unit tests are failing due to issues not related to your change. I'd like to see the result of the automated run of unit tests so I have moved this from WIP to needs review which should kick that off.

review: Needs Fixing
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #157 keystone-next for ajkavanagh mp285608
    AMULET OK: passed

Build: http://10.245.162.36:8080/job/charm_amulet_test/157/

Revision history for this message
Alex Kavanagh (ajkavanagh) wrote :

> One, we have some text conflicts that need to be resolved.

I'm guessing this means some more changes in keystone?

I'm also guessing we need to get the charm-helpers change(s) merged first, then re-sync on keystone (on this one) + any further changes on keystone, and get that in as a merge? Also, did the 'determine_ports()' change alleviate your concerns around ports and HA?

Thanks again for the review :)

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

Alex, Sorry about this I meant my comments above to be on the Charm helpers MP.

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #832 keystone-next for ajkavanagh mp285608
    LINT OK: passed

Build: http://10.245.162.36:8080/job/charm_lint_check/832/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #735 keystone-next for ajkavanagh mp285608
    UNIT OK: passed

Build: http://10.245.162.36:8080/job/charm_unit_test/735/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #333 keystone-next for ajkavanagh mp285608
    AMULET OK: passed

Build: http://10.245.162.36:8080/job/charm_amulet_test/333/

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

> > One, we have some text conflicts that need to be resolved.
>
> I'm guessing this means some more changes in keystone?

We still have text conflicts for this one.

bzr branch lp:~openstack-charmers/charms/trusty/keystone/next
cd keystone
bzr merge lp:~ajkavanagh/charms/trusty/keystone/add-service-checks-lp1524388
bzr st # shows text conflicts

> I'm also guessing we need to get the charm-helpers change(s) merged first,
> then re-sync on keystone (on this one) + any further changes on keystone, and
> get that in as a merge? Also, did the 'determine_ports()' change alleviate
> your concerns around ports and HA?
>
> Thanks again for the review :)

CH changes were merged. They may need to be resynced to fix part of the above text conflicts.

I like the determine_ports() solution. We might want to add the ports the keystone service is listening on as well (not haproxy) for extra thouroughness. 35347 and 4990 while still including the well known ports 35357 and 5000.

After the above is resolved, we can merge this thing.

review: Needs Fixing
201. By Alex Kavanagh

Resync charmhelpers to current version

202. By Alex Kavanagh

Merge keystone/next into change to get ready for final merge

Revision history for this message
Alex Kavanagh (ajkavanagh) wrote :

> > > One, we have some text conflicts that need to be resolved.
> >
> > I'm guessing this means some more changes in keystone?
>
> We still have text conflicts for this one.
>
> bzr branch lp:~openstack-charmers/charms/trusty/keystone/next
> cd keystone
> bzr merge lp:~ajkavanagh/charms/trusty/keystone/add-service-checks-lp1524388
> bzr st # shows text conflicts
>
> > I'm also guessing we need to get the charm-helpers change(s) merged first,
> > then re-sync on keystone (on this one) + any further changes on keystone,
> and
> > get that in as a merge? Also, did the 'determine_ports()' change alleviate
> > your concerns around ports and HA?
> >
> > Thanks again for the review :)
>
> CH changes were merged. They may need to be resynced to fix part of the above
> text conflicts.
>
> I like the determine_ports() solution. We might want to add the ports the
> keystone service is listening on as well (not haproxy) for extra
> thouroughness. 35347 and 4990 while still including the well known ports 35357
> and 5000.
>
> After the above is resolved, we can merge this thing.

Sortee the CH changes and also merged latest keystone/next into the branch.

Re the extra ports, would you like them hard-coded into the file, or determined from config (if there is any?)

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #917 keystone-next for ajkavanagh mp285608
    LINT OK: passed

Build: http://10.245.162.36:8080/job/charm_lint_check/917/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #817 keystone-next for ajkavanagh mp285608
    UNIT OK: passed

Build: http://10.245.162.36:8080/job/charm_unit_test/817/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #363 keystone-next for ajkavanagh mp285608
    AMULET OK: passed

Build: http://10.245.162.36:8080/job/charm_amulet_test/363/

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

This looks good. We can discuss the other ports in our next meeting and do a trivial push if needed.
Merging.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'charmhelpers/contrib/network/ip.py'
--- charmhelpers/contrib/network/ip.py 2016-01-04 21:27:51 +0000
+++ charmhelpers/contrib/network/ip.py 2016-02-19 14:51:35 +0000
@@ -456,3 +456,18 @@
456 return result456 return result
457 else:457 else:
458 return result.split('.')[0]458 return result.split('.')[0]
459
460
461def port_has_listener(address, port):
462 """
463 Returns True if the address:port is open and being listened to,
464 else False.
465
466 @param address: an IP address or hostname
467 @param port: integer port
468
469 Note calls 'zc' via a subprocess shell
470 """
471 cmd = ['nc', '-z', address, str(port)]
472 result = subprocess.call(cmd)
473 return not(bool(result))
459474
=== modified file 'charmhelpers/contrib/openstack/context.py'
--- charmhelpers/contrib/openstack/context.py 2016-02-11 14:43:33 +0000
+++ charmhelpers/contrib/openstack/context.py 2016-02-19 14:51:35 +0000
@@ -410,6 +410,7 @@
410 auth_host = format_ipv6_addr(auth_host) or auth_host410 auth_host = format_ipv6_addr(auth_host) or auth_host
411 svc_protocol = rdata.get('service_protocol') or 'http'411 svc_protocol = rdata.get('service_protocol') or 'http'
412 auth_protocol = rdata.get('auth_protocol') or 'http'412 auth_protocol = rdata.get('auth_protocol') or 'http'
413 api_version = rdata.get('api_version') or '2.0'
413 ctxt.update({'service_port': rdata.get('service_port'),414 ctxt.update({'service_port': rdata.get('service_port'),
414 'service_host': serv_host,415 'service_host': serv_host,
415 'auth_host': auth_host,416 'auth_host': auth_host,
@@ -418,7 +419,8 @@
418 'admin_user': rdata.get('service_username'),419 'admin_user': rdata.get('service_username'),
419 'admin_password': rdata.get('service_password'),420 'admin_password': rdata.get('service_password'),
420 'service_protocol': svc_protocol,421 'service_protocol': svc_protocol,
421 'auth_protocol': auth_protocol})422 'auth_protocol': auth_protocol,
423 'api_version': api_version})
422424
423 if self.context_complete(ctxt):425 if self.context_complete(ctxt):
424 # NOTE(jamespage) this is required for >= icehouse426 # NOTE(jamespage) this is required for >= icehouse
@@ -1471,6 +1473,8 @@
1471 rdata.get('service_protocol') or 'http',1473 rdata.get('service_protocol') or 'http',
1472 'auth_protocol':1474 'auth_protocol':
1473 rdata.get('auth_protocol') or 'http',1475 rdata.get('auth_protocol') or 'http',
1476 'api_version':
1477 rdata.get('api_version') or '2.0',
1474 }1478 }
1475 if self.context_complete(ctxt):1479 if self.context_complete(ctxt):
1476 return ctxt1480 return ctxt
14771481
=== modified file 'charmhelpers/contrib/openstack/templates/section-keystone-authtoken'
--- charmhelpers/contrib/openstack/templates/section-keystone-authtoken 2015-03-25 09:18:33 +0000
+++ charmhelpers/contrib/openstack/templates/section-keystone-authtoken 2016-02-19 14:51:35 +0000
@@ -1,4 +1,14 @@
1{% if auth_host -%}1{% if auth_host -%}
2{% if api_version == '3' -%}
3[keystone_authtoken]
4auth_url = {{ service_protocol }}://{{ service_host }}:{{ service_port }}
5project_name = {{ admin_tenant_name }}
6username = {{ admin_user }}
7password = {{ admin_password }}
8project_domain_name = default
9user_domain_name = default
10auth_plugin = password
11{% else -%}
2[keystone_authtoken]12[keystone_authtoken]
3identity_uri = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/{{ auth_admin_prefix }}13identity_uri = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/{{ auth_admin_prefix }}
4auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/{{ service_admin_prefix }}14auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/{{ service_admin_prefix }}
@@ -7,3 +17,4 @@
7admin_password = {{ admin_password }}17admin_password = {{ admin_password }}
8signing_dir = {{ signing_dir }}18signing_dir = {{ signing_dir }}
9{% endif -%}19{% endif -%}
20{% endif -%}
1021
=== modified file 'charmhelpers/contrib/openstack/utils.py'
--- charmhelpers/contrib/openstack/utils.py 2016-02-11 15:44:13 +0000
+++ charmhelpers/contrib/openstack/utils.py 2016-02-19 14:51:35 +0000
@@ -23,6 +23,7 @@
23import os23import os
24import sys24import sys
25import re25import re
26import itertools
2627
27import six28import six
28import tempfile29import tempfile
@@ -60,6 +61,7 @@
60from charmhelpers.contrib.network.ip import (61from charmhelpers.contrib.network.ip import (
61 get_ipv6_addr,62 get_ipv6_addr,
62 is_ipv6,63 is_ipv6,
64 port_has_listener,
63)65)
6466
65from charmhelpers.contrib.python.packages import (67from charmhelpers.contrib.python.packages import (
@@ -67,7 +69,7 @@
67 pip_install,69 pip_install,
68)70)
6971
70from charmhelpers.core.host import lsb_release, mounts, umount72from charmhelpers.core.host import lsb_release, mounts, umount, service_running
71from charmhelpers.fetch import apt_install, apt_cache, install_remote73from charmhelpers.fetch import apt_install, apt_cache, install_remote
72from charmhelpers.contrib.storage.linux.utils import is_block_device, zap_disk74from charmhelpers.contrib.storage.linux.utils import is_block_device, zap_disk
73from charmhelpers.contrib.storage.linux.loopback import ensure_loopback_device75from charmhelpers.contrib.storage.linux.loopback import ensure_loopback_device
@@ -860,13 +862,23 @@
860 return wrap862 return wrap
861863
862864
863def set_os_workload_status(configs, required_interfaces, charm_func=None):865def set_os_workload_status(configs, required_interfaces, charm_func=None, services=None, ports=None):
864 """866 """
865 Set workload status based on complete contexts.867 Set workload status based on complete contexts.
866 status-set missing or incomplete contexts868 status-set missing or incomplete contexts
867 and juju-log details of missing required data.869 and juju-log details of missing required data.
868 charm_func is a charm specific function to run checking870 charm_func is a charm specific function to run checking
869 for charm specific requirements such as a VIP setting.871 for charm specific requirements such as a VIP setting.
872
873 This function also checks for whether the services defined are ACTUALLY
874 running and that the ports they advertise are open and being listened to.
875
876 @param services - OPTIONAL: a [{'service': <string>, 'ports': [<int>]]
877 The ports are optional.
878 If services is a [<string>] then ports are ignored.
879 @param ports - OPTIONAL: an [<int>] representing ports that shoudl be
880 open.
881 @returns None
870 """882 """
871 incomplete_rel_data = incomplete_relation_data(configs, required_interfaces)883 incomplete_rel_data = incomplete_relation_data(configs, required_interfaces)
872 state = 'active'884 state = 'active'
@@ -945,6 +957,65 @@
945 else:957 else:
946 message = charm_message958 message = charm_message
947959
960 # If the charm thinks the unit is active, check that the actual services
961 # really are active.
962 if services is not None and state == 'active':
963 # if we're passed the dict() then just grab the values as a list.
964 if isinstance(services, dict):
965 services = services.values()
966 # either extract the list of services from the dictionary, or if
967 # it is a simple string, use that. i.e. works with mixed lists.
968 _s = []
969 for s in services:
970 if isinstance(s, dict) and 'service' in s:
971 _s.append(s['service'])
972 if isinstance(s, str):
973 _s.append(s)
974 services_running = [service_running(s) for s in _s]
975 if not all(services_running):
976 not_running = [s for s, running in zip(_s, services_running)
977 if not running]
978 message = ("Services not running that should be: {}"
979 .format(", ".join(not_running)))
980 state = 'blocked'
981 # also verify that the ports that should be open are open
982 # NB, that ServiceManager objects only OPTIONALLY have ports
983 port_map = OrderedDict([(s['service'], s['ports'])
984 for s in services if 'ports' in s])
985 if state == 'active' and port_map:
986 all_ports = list(itertools.chain(*port_map.values()))
987 ports_open = [port_has_listener('0.0.0.0', p)
988 for p in all_ports]
989 if not all(ports_open):
990 not_opened = [p for p, opened in zip(all_ports, ports_open)
991 if not opened]
992 map_not_open = OrderedDict()
993 for service, ports in port_map.items():
994 closed_ports = set(ports).intersection(not_opened)
995 if closed_ports:
996 map_not_open[service] = closed_ports
997 # find which service has missing ports. They are in service
998 # order which makes it a bit easier.
999 message = (
1000 "Services with ports not open that should be: {}"
1001 .format(
1002 ", ".join([
1003 "{}: [{}]".format(
1004 service,
1005 ", ".join([str(v) for v in ports]))
1006 for service, ports in map_not_open.items()])))
1007 state = 'blocked'
1008
1009 if ports is not None and state == 'active':
1010 # and we can also check ports which we don't know the service for
1011 ports_open = [port_has_listener('0.0.0.0', p) for p in ports]
1012 if not all(ports_open):
1013 message = (
1014 "Ports which should be open, but are not: {}"
1015 .format(", ".join([str(p) for p, v in zip(ports, ports_open)
1016 if not v])))
1017 state = 'blocked'
1018
948 # Set to active if all requirements have been met1019 # Set to active if all requirements have been met
949 if state == 'active':1020 if state == 'active':
950 message = "Unit is ready"1021 message = "Unit is ready"
9511022
=== modified file 'hooks/keystone_utils.py'
--- hooks/keystone_utils.py 2016-02-18 10:02:59 +0000
+++ hooks/keystone_utils.py 2016-02-19 14:51:35 +0000
@@ -1871,4 +1871,5 @@
18711871
1872 # set the status according to the current state of the contexts1872 # set the status according to the current state of the contexts
1873 set_os_workload_status(1873 set_os_workload_status(
1874 configs, REQUIRED_INTERFACES, charm_func=check_optional_relations)1874 configs, REQUIRED_INTERFACES, charm_func=check_optional_relations,
1875 services=services(), ports=determine_ports())
18751876
=== modified file 'unit_tests/test_keystone_utils.py'
--- unit_tests/test_keystone_utils.py 2016-01-19 16:54:03 +0000
+++ unit_tests/test_keystone_utils.py 2016-02-19 14:51:35 +0000
@@ -758,4 +758,6 @@
758 set_os_workload_status.assert_called_with(758 set_os_workload_status.assert_called_with(
759 "TEST CONFIG",759 "TEST CONFIG",
760 utils.REQUIRED_INTERFACES,760 utils.REQUIRED_INTERFACES,
761 charm_func=utils.check_optional_relations)761 charm_func=utils.check_optional_relations,
762 services=['haproxy', 'keystone', 'apache2'],
763 ports=[5000, 35357])

Subscribers

People subscribed via source and target branches