Merge lp:~brad-marshall/charms/trusty/ntp/add-auto-peers into lp:charms/trusty/ntp
- Trusty Tahr (14.04)
- add-auto-peers
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 19 |
Proposed branch: | lp:~brad-marshall/charms/trusty/ntp/add-auto-peers |
Merge into: | lp:charms/trusty/ntp |
Diff against target: |
265 lines (+89/-19) 6 files modified
README.md (+12/-3) config.yaml (+13/-1) hooks/ntp_hooks.py (+33/-3) metadata.yaml (+3/-0) templates/ntp.conf (+5/-0) tests/10-deploy-test.py (+23/-12) |
To merge this branch: | bzr merge lp:~brad-marshall/charms/trusty/ntp/add-auto-peers |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Charles Butler (community) | Approve | ||
Adam Israel (community) | Approve | ||
Whit Morriss (community) | Needs Fixing | ||
Cory Johns (community) | Needs Fixing | ||
Marco Ceppi (community) | Needs Fixing | ||
Review via email: mp+253132@code.launchpad.net |
Commit message
Description of the change
Add auto_peers and peers option to manage setting peers both manually and automatically between subordinates. Added a use_iburst option to speed up the initial sync period.
Mick Gregg (macgreagoir) wrote : | # |
Marco Ceppi (marcoceppi) wrote : | # |
This has conflicts with a upstream as it is. Could you please correct these and move merge back in to a "Needs Review" state. Otherwise, LGTM
Brad Marshall (brad-marshall) wrote : | # |
Ah, yes - it conflicts with my other ntp change I got merged. I'll fix that now.
Cory Johns (johnsca) wrote : | # |
Brad,
This change looks mostly good, and the merge conflict has been resolved. However, I have two items that I think should be addressed before I can give my +1:
* Missing default value for nagios_
* A test case for the auto-peering should be added (maybe just a couple of lines could be added to 10-deploy-test.py?)
I'm also a little confused about the purpose of the "total_sources" option? Is it really useful to have an option whose only effect is to create a log message? Is there more behavior that will be coming to this option?
Brad Marshall (brad-marshall) wrote : | # |
Ok, I've fixed the nagios_servicegroup issue, added a test for the peers and removed the total_source line - I was going to do a nagios test but ran out of time to get it sorted correctly. I'll add it back later if I get the chance.
Brad Marshall (brad-marshall) wrote : | # |
Somehow I've managed to lose my nrpe changes in this from my other MP, I'll fix that up before resubmitting it.
Brad Marshall (brad-marshall) wrote : | # |
This should be ready for review now - once this lands I'll look at doing similar for ntpmaster.
Whit Morriss (whitmo) wrote : | # |
LGTM once you add this test fix. Looks like a minor typo that didn't get pushed.
https:/
Merges cleanly, all tests pass.
- 37. By Brad Marshall
-
[bradm] Fixed unit name on the test
Brad Marshall (brad-marshall) wrote : | # |
Thanks for catching that, I must have missed pushing up my latest rev somehow. All merged, ready for review.
Adam Israel (aisrael) wrote : | # |
Hi Brad,
I had the chance to review your latest revision, and everything passes cleanly for me. +1
Charles Butler (lazypower) wrote : | # |
There's one fix I'd like to comment on with this branch.
It appears there's a bug in the setup routine that isn't installing amulet for the python version under test.
http://
I've pulled the tests and run them manually and while the dependency is present, I was unable to get a successful test run:
Traceback (most recent call last):
File "/tmp/bundletes
configurati
This returned on all tested substrates.
Once this is fixed up I'll be happy to approve and merge.
Thanks for all the hard work already @brad-marshall, I look forward to ack'ing this MP soon.
Charles Butler (lazypower) wrote : | # |
I circled back and cleaned up the tests to pass.
Thanks for the contribution! Make sure that you backport the changes from tests/10-
+1 LGTM. Thank you for taking the time to submit this fix for the charm store. We appreciate your work. I've merged this branch and it should be available in the charm store after the next ingestion.
If you have any questions/
Preview Diff
1 | === modified file 'README.md' | |||
2 | --- README.md 2013-08-29 13:50:54 +0000 | |||
3 | +++ README.md 2015-04-01 00:26:30 +0000 | |||
4 | @@ -27,11 +27,20 @@ | |||
5 | 27 | 27 | ||
6 | 28 | juju set ntp source=myatomiclock.local.net | 28 | juju set ntp source=myatomiclock.local.net |
7 | 29 | 29 | ||
9 | 30 | You can also specify multiple sources: | 30 | You can also specify multiple sources and peers: |
10 | 31 | 31 | ||
11 | 32 | juju set ntp source="mac1.local.net mac2.local.net mac3.local.net" | 32 | juju set ntp source="mac1.local.net mac2.local.net mac3.local.net" |
14 | 33 | 33 | juju set ntp peers="mac1.local.net mac2.local.net mac3.local.net" | |
15 | 34 | Sources should be space separated. | 34 | |
16 | 35 | Sources and peers should be space separated. | ||
17 | 36 | |||
18 | 37 | When you need a set of services to keep close time to each other, it may | ||
19 | 38 | be useful to have them automatically peer with each other. This means | ||
20 | 39 | any set of services that use the same ntp subordinate will peer together. | ||
21 | 40 | |||
22 | 41 | juju set ntp auto_peers=true | ||
23 | 42 | |||
24 | 43 | This will add all the hosts as peers to each other. | ||
25 | 35 | 44 | ||
26 | 36 | Mastered | 45 | Mastered |
27 | 37 | ======== | 46 | ======== |
28 | 38 | 47 | ||
29 | === modified file 'config.yaml' | |||
30 | --- config.yaml 2015-03-23 00:39:09 +0000 | |||
31 | +++ config.yaml 2015-04-01 00:26:30 +0000 | |||
32 | @@ -3,6 +3,10 @@ | |||
33 | 3 | default: "" | 3 | default: "" |
34 | 4 | type: string | 4 | type: string |
35 | 5 | description: Space separated list of NTP servers to use as source for time. | 5 | description: Space separated list of NTP servers to use as source for time. |
36 | 6 | peers: | ||
37 | 7 | default: "" | ||
38 | 8 | type: string | ||
39 | 9 | description: Space separated list of NTP servers to use as peers for time. | ||
40 | 6 | nagios_context: | 10 | nagios_context: |
41 | 7 | default: "juju" | 11 | default: "juju" |
42 | 8 | type: string | 12 | type: string |
43 | @@ -13,7 +17,7 @@ | |||
44 | 13 | juju-myservice-0 | 17 | juju-myservice-0 |
45 | 14 | If you're running multiple environments with the same services in them | 18 | If you're running multiple environments with the same services in them |
46 | 15 | this allows you to differentiate between them. | 19 | this allows you to differentiate between them. |
48 | 16 | nagios_servicegroups: | 20 | nagios_servicegroups: |
49 | 17 | default: "" | 21 | default: "" |
50 | 18 | type: string | 22 | type: string |
51 | 19 | description: | | 23 | description: | |
52 | @@ -25,3 +29,11 @@ | |||
53 | 25 | description: | | 29 | description: | |
54 | 26 | A space-seperated list of nagios ntpmon checks to enable. | 30 | A space-seperated list of nagios ntpmon checks to enable. |
55 | 27 | If left empty, no ntpmon checks will be used. | 31 | If left empty, no ntpmon checks will be used. |
56 | 32 | auto_peers: | ||
57 | 33 | default: false | ||
58 | 34 | type: boolean | ||
59 | 35 | description: Will ntp auto peer between the environment | ||
60 | 36 | use_iburst: | ||
61 | 37 | default: false | ||
62 | 38 | type: boolean | ||
63 | 39 | description: Use iburst for all servers, not just ntpmaster | ||
64 | 28 | 40 | ||
65 | === added symlink 'hooks/ntp-peers-relation-changed' | |||
66 | === target is u'ntp_hooks.py' | |||
67 | === added symlink 'hooks/ntp-peers-relation-joined' | |||
68 | === target is u'ntp_hooks.py' | |||
69 | === modified file 'hooks/ntp_hooks.py' | |||
70 | --- hooks/ntp_hooks.py 2015-03-23 00:51:20 +0000 | |||
71 | +++ hooks/ntp_hooks.py 2015-04-01 00:26:30 +0000 | |||
72 | @@ -19,6 +19,17 @@ | |||
73 | 19 | hooks = hookenv.Hooks() | 19 | hooks = hookenv.Hooks() |
74 | 20 | 20 | ||
75 | 21 | 21 | ||
76 | 22 | def get_peer_nodes(): | ||
77 | 23 | hosts = [] | ||
78 | 24 | hosts.append(hookenv.unit_get('private-address')) | ||
79 | 25 | for relid in hookenv.relation_ids('ntp-peers'): | ||
80 | 26 | for unit in hookenv.related_units(relid): | ||
81 | 27 | hosts.append(hookenv.relation_get('private-address', | ||
82 | 28 | unit, relid)) | ||
83 | 29 | hosts.sort() | ||
84 | 30 | return hosts | ||
85 | 31 | |||
86 | 32 | |||
87 | 22 | @hooks.hook('install') | 33 | @hooks.hook('install') |
88 | 23 | def install(): | 34 | def install(): |
89 | 24 | fetch.apt_update(fatal=True) | 35 | fetch.apt_update(fatal=True) |
90 | @@ -30,27 +41,46 @@ | |||
91 | 30 | @hooks.hook('config-changed') | 41 | @hooks.hook('config-changed') |
92 | 31 | @hooks.hook('master-relation-changed') | 42 | @hooks.hook('master-relation-changed') |
93 | 32 | @hooks.hook('master-relation-departed') | 43 | @hooks.hook('master-relation-departed') |
94 | 44 | @hooks.hook('ntp-peers-relation-joined', | ||
95 | 45 | 'ntp-peers-relation-changed') | ||
96 | 33 | @host.restart_on_change({NTP_CONF: ['ntp']}) | 46 | @host.restart_on_change({NTP_CONF: ['ntp']}) |
97 | 34 | def write_config(): | 47 | def write_config(): |
98 | 48 | use_iburst = hookenv.config('use_iburst') | ||
99 | 35 | source = hookenv.config('source') | 49 | source = hookenv.config('source') |
100 | 36 | remote_sources = [] | 50 | remote_sources = [] |
101 | 37 | if source: | 51 | if source: |
102 | 38 | for s in source.split(" "): | 52 | for s in source.split(" "): |
103 | 39 | if len(s) > 0: | 53 | if len(s) > 0: |
105 | 40 | remote_sources.append({'name': s}) | 54 | if use_iburst: |
106 | 55 | remote_sources.append({'name': '%s iburst' % s}) | ||
107 | 56 | else: | ||
108 | 57 | remote_sources.append({'name': s}) | ||
109 | 41 | for relid in hookenv.relation_ids('master'): | 58 | for relid in hookenv.relation_ids('master'): |
110 | 42 | for unit in hookenv.related_units(relid=relid): | 59 | for unit in hookenv.related_units(relid=relid): |
111 | 43 | u_addr = hookenv.relation_get(attribute='private-address', | 60 | u_addr = hookenv.relation_get(attribute='private-address', |
112 | 44 | unit=unit, rid=relid) | 61 | unit=unit, rid=relid) |
113 | 45 | remote_sources.append({'name': '%s iburst' % u_addr}) | 62 | remote_sources.append({'name': '%s iburst' % u_addr}) |
114 | 46 | 63 | ||
115 | 64 | auto_peers = hookenv.config('auto_peers') | ||
116 | 65 | peers = hookenv.config('peers') | ||
117 | 66 | remote_peers = [] | ||
118 | 67 | if peers: | ||
119 | 68 | for p in peers.split(" "): | ||
120 | 69 | if len(p) > 0: | ||
121 | 70 | remote_peers.append(p) | ||
122 | 71 | if hookenv.relation_ids('ntp-peers'): | ||
123 | 72 | if auto_peers: | ||
124 | 73 | for rp in get_peer_nodes(): | ||
125 | 74 | remote_peers.append(rp) | ||
126 | 75 | |||
127 | 47 | if len(remote_sources) == 0: | 76 | if len(remote_sources) == 0: |
128 | 48 | shutil.copy(NTP_CONF_ORIG, NTP_CONF) | 77 | shutil.copy(NTP_CONF_ORIG, NTP_CONF) |
129 | 49 | else: | 78 | else: |
130 | 50 | with open(NTP_CONF, "w") as ntpconf: | 79 | with open(NTP_CONF, "w") as ntpconf: |
131 | 51 | ntpconf.write(render(os.path.basename(NTP_CONF), | 80 | ntpconf.write(render(os.path.basename(NTP_CONF), |
134 | 52 | {'servers': remote_sources})) | 81 | {'servers': remote_sources, |
135 | 53 | 82 | 'peers': remote_peers, | |
136 | 83 | 'use_iburst': use_iburst})) | ||
137 | 54 | update_nrpe_config() | 84 | update_nrpe_config() |
138 | 55 | 85 | ||
139 | 56 | 86 | ||
140 | 57 | 87 | ||
141 | === modified file 'metadata.yaml' | |||
142 | --- metadata.yaml 2015-03-17 04:10:30 +0000 | |||
143 | +++ metadata.yaml 2015-04-01 00:26:30 +0000 | |||
144 | @@ -22,3 +22,6 @@ | |||
145 | 22 | scope: container | 22 | scope: container |
146 | 23 | master: | 23 | master: |
147 | 24 | interface: ntp | 24 | interface: ntp |
148 | 25 | peers: | ||
149 | 26 | ntp-peers: | ||
150 | 27 | interface: ntp | ||
151 | 25 | 28 | ||
152 | === modified file 'templates/ntp.conf' | |||
153 | --- templates/ntp.conf 2013-07-15 14:26:04 +0000 | |||
154 | +++ templates/ntp.conf 2015-04-01 00:26:30 +0000 | |||
155 | @@ -8,6 +8,11 @@ | |||
156 | 8 | restrict -6 default kod notrap nomodify nopeer noquery | 8 | restrict -6 default kod notrap nomodify nopeer noquery |
157 | 9 | restrict 127.0.0.1 | 9 | restrict 127.0.0.1 |
158 | 10 | restrict ::1 | 10 | restrict ::1 |
159 | 11 | {% for peer in peers %}restrict {{ peer }} kod notrap nomodify | ||
160 | 12 | {% endfor %} | ||
161 | 11 | # SERVERS | 13 | # SERVERS |
162 | 12 | {% for server in servers %}server {{ server.name }} | 14 | {% for server in servers %}server {{ server.name }} |
163 | 13 | {% endfor %} | 15 | {% endfor %} |
164 | 16 | # PEERS | ||
165 | 17 | {% for peer in peers %}peer {{ peer }} {% if use_iburst %}iburst{% endif %} | ||
166 | 18 | {% endfor %} | ||
167 | 14 | 19 | ||
168 | === modified file 'tests/10-deploy-test.py' | |||
169 | --- tests/10-deploy-test.py 2014-06-18 18:11:00 +0000 | |||
170 | +++ tests/10-deploy-test.py 2015-04-01 00:26:30 +0000 | |||
171 | @@ -5,35 +5,36 @@ | |||
172 | 5 | import amulet | 5 | import amulet |
173 | 6 | 6 | ||
174 | 7 | # The number of seconds to wait for Juju to set up the environment. | 7 | # The number of seconds to wait for Juju to set up the environment. |
176 | 8 | seconds = 900 | 8 | seconds = 9600 |
177 | 9 | ntp_server_0 = 'ntp.your.org' | 9 | ntp_server_0 = 'ntp.your.org' |
178 | 10 | ntp_server_1 = 'us.pool.ntp.org' | 10 | ntp_server_1 = 'us.pool.ntp.org' |
179 | 11 | ntp_server_2 = 'tock.mtnlion.com' | 11 | ntp_server_2 = 'tock.mtnlion.com' |
180 | 12 | 12 | ||
181 | 13 | # The ntp configuration to test. | 13 | # The ntp configuration to test. |
182 | 14 | ntp_configuration = { | 14 | ntp_configuration = { |
184 | 15 | 'source': ntp_server_0 + ' ' + ntp_server_1 + ' ' + ntp_server_2 | 15 | 'source': ntp_server_0 + ' ' + ntp_server_1 + ' ' + ntp_server_2, |
185 | 16 | 'auto_peers': True | ||
186 | 16 | } | 17 | } |
187 | 17 | 18 | ||
189 | 18 | d = amulet.Deployment() | 19 | d = amulet.Deployment(series='trusty', juju_deployer='juju-deployer -d -v') |
190 | 19 | # Add the ntp charm to the deployment. | 20 | # Add the ntp charm to the deployment. |
191 | 20 | d.add('ntp') | 21 | d.add('ntp') |
192 | 21 | # Add the ntpmaster charm to the deployment. | 22 | # Add the ntpmaster charm to the deployment. |
193 | 22 | d.add('ntpmaster') | 23 | d.add('ntpmaster') |
194 | 23 | # Add the ubuntu charm to the deployment. | 24 | # Add the ubuntu charm to the deployment. |
196 | 24 | d.add('ubuntu') | 25 | d.add('ubuntu', units=2) |
197 | 25 | # Configure the ntp charm. | 26 | # Configure the ntp charm. |
198 | 26 | d.configure('ntp', ntp_configuration) | 27 | d.configure('ntp', ntp_configuration) |
199 | 27 | 28 | ||
200 | 29 | # Relate the ntp and the ubuntu charm. | ||
201 | 30 | d.relate('ntp:juju-info', 'ubuntu:juju-info') | ||
202 | 28 | # Relate the ntp and ntpmaster charms. | 31 | # Relate the ntp and ntpmaster charms. |
203 | 29 | d.relate('ntp:master', 'ntpmaster:master') | 32 | d.relate('ntp:master', 'ntpmaster:master') |
204 | 30 | # Relate the ntp and the ubuntu charm. | ||
205 | 31 | d.relate('ntp:juju-info', 'ubuntu:juju-info') | ||
206 | 32 | 33 | ||
207 | 33 | # Deploy the environment and wait for it to setup. | 34 | # Deploy the environment and wait for it to setup. |
208 | 34 | try: | 35 | try: |
209 | 35 | d.setup(timeout=seconds) | 36 | d.setup(timeout=seconds) |
211 | 36 | d.sentry.wait(seconds) | 37 | d.sentry.wait(timeout=seconds) |
212 | 37 | except amulet.helpers.TimeoutError: | 38 | except amulet.helpers.TimeoutError: |
213 | 38 | message = 'The environment did not setup in %d seconds.' % seconds | 39 | message = 'The environment did not setup in %d seconds.' % seconds |
214 | 39 | # The SKIP status enables skip or fail the test based on configuration. | 40 | # The SKIP status enables skip or fail the test based on configuration. |
215 | @@ -48,7 +49,8 @@ | |||
216 | 48 | ntpmaster_unit = d.sentry.unit['ntpmaster/0'] | 49 | ntpmaster_unit = d.sentry.unit['ntpmaster/0'] |
217 | 49 | 50 | ||
218 | 50 | # Get the sentry unit for ubuntu. | 51 | # Get the sentry unit for ubuntu. |
220 | 51 | ubuntu_unit = d.sentry.unit['ubuntu/0'] | 52 | ubuntu_unit_0 = d.sentry.unit['ubuntu/0'] |
221 | 53 | ubuntu_unit_1 = d.sentry.unit['ubuntu/1'] | ||
222 | 52 | 54 | ||
223 | 53 | # Get the public address for the system running the ntmpmaster charm. | 55 | # Get the public address for the system running the ntmpmaster charm. |
224 | 54 | master_public_address = ntpmaster_unit.info['public-address'] | 56 | master_public_address = ntpmaster_unit.info['public-address'] |
225 | @@ -59,22 +61,27 @@ | |||
226 | 59 | master_private_address = master_relation['private-address'] | 61 | master_private_address = master_relation['private-address'] |
227 | 60 | print('ntpmaster private address ' + master_private_address) | 62 | print('ntpmaster private address ' + master_private_address) |
228 | 61 | 63 | ||
229 | 64 | ubuntu_0_public_address = ubuntu_unit_0.info['public-address'] | ||
230 | 65 | print('ubuntu/0 public address ' + ubuntu_0_public_address) | ||
231 | 66 | ubuntu_1_public_address = ubuntu_unit_1.info['public-address'] | ||
232 | 67 | print('ubuntu/1 public address ' + ubuntu_1_public_address) | ||
233 | 68 | |||
234 | 62 | # Create a command to check the ntp service. | 69 | # Create a command to check the ntp service. |
235 | 63 | command = 'sudo service ntp status' | 70 | command = 'sudo service ntp status' |
236 | 64 | print(command) | 71 | print(command) |
239 | 65 | # Run the command to see if apache2 is running. | 72 | # Run the command to see if ntp is running. |
240 | 66 | output, code = ubuntu_unit.run(command) | 73 | output, code = ubuntu_unit_0.run(command) |
241 | 67 | print(output) | 74 | print(output) |
242 | 68 | if code != 0 or output.find('NTP server is running') == -1: | 75 | if code != 0 or output.find('NTP server is running') == -1: |
243 | 69 | message = 'The NTP service is not running on the ubuntu unit.' | 76 | message = 'The NTP service is not running on the ubuntu unit.' |
244 | 70 | print(message) | 77 | print(message) |
245 | 71 | amulet.raise_status(amulet.FAIL, msg=message) | 78 | amulet.raise_status(amulet.FAIL, msg=message) |
246 | 72 | 79 | ||
248 | 73 | # The ubuntu cloud image does not have ntp installed by default, | 80 | # The ubuntu cloud image does not have ntp installed by default, |
249 | 74 | # and therefore does not have the /etc/ntp.conf file. | 81 | # and therefore does not have the /etc/ntp.conf file. |
250 | 75 | 82 | ||
251 | 76 | # Read in the ntp configuration file from the ubuntu unit. | 83 | # Read in the ntp configuration file from the ubuntu unit. |
253 | 77 | configuration_file = ubuntu_unit.file_contents('/etc/ntp.conf') | 84 | configuration_file = ubuntu_unit_0.file_contents('/etc/ntp.conf') |
254 | 78 | # This call will fail with an IO exception if the file does not exist. | 85 | # This call will fail with an IO exception if the file does not exist. |
255 | 79 | 86 | ||
256 | 80 | # Search for ntp server 0 in the config file, raise an exception if not found. | 87 | # Search for ntp server 0 in the config file, raise an exception if not found. |
257 | @@ -87,4 +94,8 @@ | |||
258 | 87 | # Search for the ntpmaster IP address in the config file, added by relation. | 94 | # Search for the ntpmaster IP address in the config file, added by relation. |
259 | 88 | configuration_file.index(master_private_address) | 95 | configuration_file.index(master_private_address) |
260 | 89 | 96 | ||
261 | 97 | # Search for ubuntu/[01] in the config file, raise an exception if not found. | ||
262 | 98 | configuration_file.index(ubuntu_0_public_address) | ||
263 | 99 | configuration_file.index(ubuntu_1_public_address) | ||
264 | 100 | |||
265 | 90 | print('The ntp deploy test completed successfully.') | 101 | print('The ntp deploy test completed successfully.') |
Tested successfully in BootStack Staging environment.