Merge lp:~bigdata-dev/charms/trusty/apache-flume-syslog/trunk into lp:charms/trusty/apache-flume-syslog

Proposed by Kevin W Monroe
Status: Merged
Merged at revision: 2
Proposed branch: lp:~bigdata-dev/charms/trusty/apache-flume-syslog/trunk
Merge into: lp:charms/trusty/apache-flume-syslog
Diff against target: 1831 lines (+1704/-0) (has conflicts)
20 files modified
LICENSE (+177/-0)
README.md (+99/-0)
config.yaml (+35/-0)
copyright (+16/-0)
dist.yaml (+18/-0)
hooks/callbacks.py (+160/-0)
hooks/common.py (+91/-0)
hooks/config-changed (+15/-0)
hooks/flume-agent-relation-changed (+15/-0)
hooks/install (+17/-0)
hooks/setup.py (+33/-0)
hooks/start (+15/-0)
hooks/stop (+15/-0)
hooks/syslog-relation-changed (+15/-0)
icon.svg (+863/-0)
metadata.yaml (+13/-0)
resources.yaml (+12/-0)
templates/flume.conf.j2 (+28/-0)
tests/00-setup (+5/-0)
tests/remote/test_dist_config.py (+62/-0)
Conflict adding file LICENSE.  Moved existing file to LICENSE.moved.
Conflict adding file README.md.  Moved existing file to README.md.moved.
Conflict adding file config.yaml.  Moved existing file to config.yaml.moved.
Conflict adding file copyright.  Moved existing file to copyright.moved.
Conflict adding file dist.yaml.  Moved existing file to dist.yaml.moved.
Conflict adding file hooks.  Moved existing file to hooks.moved.
Conflict adding file icon.svg.  Moved existing file to icon.svg.moved.
Conflict adding file metadata.yaml.  Moved existing file to metadata.yaml.moved.
Conflict adding file resources.  Moved existing file to resources.moved.
Conflict adding file resources.yaml.  Moved existing file to resources.yaml.moved.
Conflict adding file templates.  Moved existing file to templates.moved.
Conflict adding file tests.  Moved existing file to tests.moved.
To merge this branch: bzr merge lp:~bigdata-dev/charms/trusty/apache-flume-syslog/trunk
Reviewer Review Type Date Requested Status
Kevin W Monroe Approve
Review via email: mp+268663@code.launchpad.net
To post a comment you must log in.
11. By Cory Johns

Fixed permissions on test_dist_config.py

Revision history for this message
Kevin W Monroe (kwmonroe) wrote :

Realtime syslog analytics bundle test looked good. Merged.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'LICENSE'
--- LICENSE 1970-01-01 00:00:00 +0000
+++ LICENSE 2015-08-21 21:55:32 +0000
@@ -0,0 +1,177 @@
1
2 Apache License
3 Version 2.0, January 2004
4 http://www.apache.org/licenses/
5
6 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
8 1. Definitions.
9
10 "License" shall mean the terms and conditions for use, reproduction,
11 and distribution as defined by Sections 1 through 9 of this document.
12
13 "Licensor" shall mean the copyright owner or entity authorized by
14 the copyright owner that is granting the License.
15
16 "Legal Entity" shall mean the union of the acting entity and all
17 other entities that control, are controlled by, or are under common
18 control with that entity. For the purposes of this definition,
19 "control" means (i) the power, direct or indirect, to cause the
20 direction or management of such entity, whether by contract or
21 otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 outstanding shares, or (iii) beneficial ownership of such entity.
23
24 "You" (or "Your") shall mean an individual or Legal Entity
25 exercising permissions granted by this License.
26
27 "Source" form shall mean the preferred form for making modifications,
28 including but not limited to software source code, documentation
29 source, and configuration files.
30
31 "Object" form shall mean any form resulting from mechanical
32 transformation or translation of a Source form, including but
33 not limited to compiled object code, generated documentation,
34 and conversions to other media types.
35
36 "Work" shall mean the work of authorship, whether in Source or
37 Object form, made available under the License, as indicated by a
38 copyright notice that is included in or attached to the work
39 (an example is provided in the Appendix below).
40
41 "Derivative Works" shall mean any work, whether in Source or Object
42 form, that is based on (or derived from) the Work and for which the
43 editorial revisions, annotations, elaborations, or other modifications
44 represent, as a whole, an original work of authorship. For the purposes
45 of this License, Derivative Works shall not include works that remain
46 separable from, or merely link (or bind by name) to the interfaces of,
47 the Work and Derivative Works thereof.
48
49 "Contribution" shall mean any work of authorship, including
50 the original version of the Work and any modifications or additions
51 to that Work or Derivative Works thereof, that is intentionally
52 submitted to Licensor for inclusion in the Work by the copyright owner
53 or by an individual or Legal Entity authorized to submit on behalf of
54 the copyright owner. For the purposes of this definition, "submitted"
55 means any form of electronic, verbal, or written communication sent
56 to the Licensor or its representatives, including but not limited to
57 communication on electronic mailing lists, source code control systems,
58 and issue tracking systems that are managed by, or on behalf of, the
59 Licensor for the purpose of discussing and improving the Work, but
60 excluding communication that is conspicuously marked or otherwise
61 designated in writing by the copyright owner as "Not a Contribution."
62
63 "Contributor" shall mean Licensor and any individual or Legal Entity
64 on behalf of whom a Contribution has been received by Licensor and
65 subsequently incorporated within the Work.
66
67 2. Grant of Copyright License. Subject to the terms and conditions of
68 this License, each Contributor hereby grants to You a perpetual,
69 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 copyright license to reproduce, prepare Derivative Works of,
71 publicly display, publicly perform, sublicense, and distribute the
72 Work and such Derivative Works in Source or Object form.
73
74 3. Grant of Patent License. Subject to the terms and conditions of
75 this License, each Contributor hereby grants to You a perpetual,
76 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 (except as stated in this section) patent license to make, have made,
78 use, offer to sell, sell, import, and otherwise transfer the Work,
79 where such license applies only to those patent claims licensable
80 by such Contributor that are necessarily infringed by their
81 Contribution(s) alone or by combination of their Contribution(s)
82 with the Work to which such Contribution(s) was submitted. If You
83 institute patent litigation against any entity (including a
84 cross-claim or counterclaim in a lawsuit) alleging that the Work
85 or a Contribution incorporated within the Work constitutes direct
86 or contributory patent infringement, then any patent licenses
87 granted to You under this License for that Work shall terminate
88 as of the date such litigation is filed.
89
90 4. Redistribution. You may reproduce and distribute copies of the
91 Work or Derivative Works thereof in any medium, with or without
92 modifications, and in Source or Object form, provided that You
93 meet the following conditions:
94
95 (a) You must give any other recipients of the Work or
96 Derivative Works a copy of this License; and
97
98 (b) You must cause any modified files to carry prominent notices
99 stating that You changed the files; and
100
101 (c) You must retain, in the Source form of any Derivative Works
102 that You distribute, all copyright, patent, trademark, and
103 attribution notices from the Source form of the Work,
104 excluding those notices that do not pertain to any part of
105 the Derivative Works; and
106
107 (d) If the Work includes a "NOTICE" text file as part of its
108 distribution, then any Derivative Works that You distribute must
109 include a readable copy of the attribution notices contained
110 within such NOTICE file, excluding those notices that do not
111 pertain to any part of the Derivative Works, in at least one
112 of the following places: within a NOTICE text file distributed
113 as part of the Derivative Works; within the Source form or
114 documentation, if provided along with the Derivative Works; or,
115 within a display generated by the Derivative Works, if and
116 wherever such third-party notices normally appear. The contents
117 of the NOTICE file are for informational purposes only and
118 do not modify the License. You may add Your own attribution
119 notices within Derivative Works that You distribute, alongside
120 or as an addendum to the NOTICE text from the Work, provided
121 that such additional attribution notices cannot be construed
122 as modifying the License.
123
124 You may add Your own copyright statement to Your modifications and
125 may provide additional or different license terms and conditions
126 for use, reproduction, or distribution of Your modifications, or
127 for any such Derivative Works as a whole, provided Your use,
128 reproduction, and distribution of the Work otherwise complies with
129 the conditions stated in this License.
130
131 5. Submission of Contributions. Unless You explicitly state otherwise,
132 any Contribution intentionally submitted for inclusion in the Work
133 by You to the Licensor shall be under the terms and conditions of
134 this License, without any additional terms or conditions.
135 Notwithstanding the above, nothing herein shall supersede or modify
136 the terms of any separate license agreement you may have executed
137 with Licensor regarding such Contributions.
138
139 6. Trademarks. This License does not grant permission to use the trade
140 names, trademarks, service marks, or product names of the Licensor,
141 except as required for reasonable and customary use in describing the
142 origin of the Work and reproducing the content of the NOTICE file.
143
144 7. Disclaimer of Warranty. Unless required by applicable law or
145 agreed to in writing, Licensor provides the Work (and each
146 Contributor provides its Contributions) on an "AS IS" BASIS,
147 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 implied, including, without limitation, any warranties or conditions
149 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 PARTICULAR PURPOSE. You are solely responsible for determining the
151 appropriateness of using or redistributing the Work and assume any
152 risks associated with Your exercise of permissions under this License.
153
154 8. Limitation of Liability. In no event and under no legal theory,
155 whether in tort (including negligence), contract, or otherwise,
156 unless required by applicable law (such as deliberate and grossly
157 negligent acts) or agreed to in writing, shall any Contributor be
158 liable to You for damages, including any direct, indirect, special,
159 incidental, or consequential damages of any character arising as a
160 result of this License or out of the use or inability to use the
161 Work (including but not limited to damages for loss of goodwill,
162 work stoppage, computer failure or malfunction, or any and all
163 other commercial damages or losses), even if such Contributor
164 has been advised of the possibility of such damages.
165
166 9. Accepting Warranty or Additional Liability. While redistributing
167 the Work or Derivative Works thereof, You may choose to offer,
168 and charge a fee for, acceptance of support, warranty, indemnity,
169 or other liability obligations and/or rights consistent with this
170 License. However, in accepting such obligations, You may act only
171 on Your own behalf and on Your sole responsibility, not on behalf
172 of any other Contributor, and only if You agree to indemnify,
173 defend, and hold each Contributor harmless for any liability
174 incurred by, or claims asserted against, such Contributor by reason
175 of your accepting any such warranty or additional liability.
176
177 END OF TERMS AND CONDITIONS
0178
=== renamed file 'LICENSE' => 'LICENSE.moved'
=== added file 'README.md'
--- README.md 1970-01-01 00:00:00 +0000
+++ README.md 2015-08-21 21:55:32 +0000
@@ -0,0 +1,99 @@
1## Overview
2
3Flume is a distributed, reliable, and available service for efficiently
4collecting, aggregating, and moving large amounts of log data. It has a simple
5and flexible architecture based on streaming data flows. It is robust and fault
6tolerant with tunable reliability mechanisms and many failover and recovery
7mechanisms. It uses a simple extensible data model that allows for online
8analytic application. Learn more at [flume.apache.org](http://flume.apache.org).
9
10This charm provides a Flume agent designed to receive remote syslog events and
11send them to the `apache-flume-hdfs` agent for storage into the shared
12filesystem (HDFS) of a connected Hadoop cluster. Think of this charm as a
13replacement for `rsyslog`, sending syslog events to HDFS instead of writing
14them to a local filesystem.
15
16
17## Usage
18
19This charm leverages our pluggable Hadoop model with the `hadoop-plugin`
20interface. This means that you will need to deploy a base Apache Hadoop cluster
21to run Flume. The suggested deployment method is to use the
22[apache-ingestion-flume](https://jujucharms.com/u/bigdata-dev/apache-ingestion-flume/)
23bundle. This will deploy the Apache Hadoop platform with a single Apache Flume
24unit that communicates with the cluster by relating to the
25`apache-hadoop-plugin` subordinate charm:
26
27 juju quickstart u/bigdata-dev/apache-ingestion-flume
28
29Alternatively, you may manually deploy the recommended environment as follows:
30
31 juju deploy apache-hadoop-hdfs-master hdfs-master
32 juju deploy apache-hadoop-yarn-master yarn-master
33 juju deploy apache-hadoop-compute-slave compute-slave
34 juju deploy apache-hadoop-plugin plugin
35 juju deploy apache-flume-hdfs flume-hdfs
36
37 juju add-relation yarn-master hdfs-master
38 juju add-relation compute-slave yarn-master
39 juju add-relation compute-slave hdfs-master
40 juju add-relation plugin yarn-master
41 juju add-relation plugin hdfs-master
42 juju add-relation flume-hdfs plugin
43
44Once the bundle has been deployed, add the `apache-flume-syslog` charm and
45relate it to the `flume-hdfs` agent:
46
47 juju deploy apache-flume-syslog flume-syslog
48 juju add-relation flume-syslog flume-hdfs
49
50You are now ready to ingest remote syslog events! Note the deployment at this
51stage isn't very useful. You'll need to relate this charm to any other service
52that is configured to send data via the `syslog` interface.
53
54As an example, let's ingest our `hdfs-master` syslog events into HDFS. Deploy
55the `rsyslog-forwarder-ha` subordinate charm, relate it to `hdfs-master`, and
56then link the `syslog` interfaces:
57
58 juju deploy rsyslog-forwarder-ha
59 juju add-relation rsyslog-forwarder-ha hdfs-master
60 juju add-relation rsyslog-forwarder-ha flume-syslog
61
62Any syslog data generated on the `hdfs-master` unit will now be ingested into
63HDFS via the `flume-syslog` and `flume-hdfs` charms. These events will be stored
64by year-month-day/hour here: `/user/flume/flume-syslog/%y-%m-%d/%H`.
65
66
67## Test the deployment
68
69To verify this charm is working as intended, trigger a syslog event on the
70monitored unit (`hdfs-master` in our deployment scenario):
71
72 juju ssh hdfs-master
73 exit
74
75Now SSH to the `flume-hdfs` unit, locate the event, and cat it:
76
77 juju ssh flume-hdfs/0
78 hdfs dfs -ls /user/flume/flume-syslog # <-- find a date
79 hdfs dfs -ls /user/flume/flume-syslog/yy-mm-dd # <-- find an hour
80 hdfs dfs -ls /user/flume/flume-syslog/yy-mm-dd/HH # <-- find an event
81 hdfs dfs -cat /user/flume/flume-syslog/yy-mm-dd/HH/FlumeData.<id>
82
83You should be able to find a timestamped message about SSH'ing into the
84`hdfs-master` unit that corresponds to the trigger you issued above. Note that
85this deployment isn't limited to ssh-related events. You'll get every syslog
86event from the `hdfs-master` unit. Happy logging!
87
88
89## Contact Information
90
91- <bigdata-dev@lists.launchpad.net>
92
93
94## Help
95
96- [Apache Flume home page](http://flume.apache.org/)
97- [Apache Flume bug tracker](https://issues.apache.org/jira/browse/flume)
98- [Apache Flume mailing lists](https://flume.apache.org/mailinglists.html)
99- `#juju` on `irc.freenode.net`
0100
=== renamed file 'README.md' => 'README.md.moved'
=== added file 'config.yaml'
--- config.yaml 1970-01-01 00:00:00 +0000
+++ config.yaml 2015-08-21 21:55:32 +0000
@@ -0,0 +1,35 @@
1options:
2 resources_mirror:
3 type: string
4 default: ''
5 description: |
6 URL from which to fetch resources (e.g., Hadoop binaries) instead
7 of Launchpad.
8 channel_capacity:
9 type: string
10 default: '1000'
11 description: |
12 The maximum number of events stored in the channel.
13 channel_transaction_capacity:
14 type: string
15 default: '100'
16 description: |
17 The maximum number of events the channel will take from a source or
18 give to a sink per transaction.
19 event_dir:
20 type: string
21 default: 'flume-syslog'
22 description: |
23 The HDFS subdirectory under /user/flume where events will be stored.
24 source_port:
25 type: string
26 default: '514'
27 description: |
28 Port on which the agent source is listening. If relating to the
29 'rsyslog-forwarder-ha' charm, this must be '514'.
30 source_type:
31 type: string
32 default: 'syslogudp'
33 description: |
34 Agent source type. Can be 'syslogudp' or 'syslogtcp'. If
35 relating to the 'rsyslog-forwarder-ha' charm, this must be 'syslogudp'.
036
=== renamed file 'config.yaml' => 'config.yaml.moved'
=== added file 'copyright'
--- copyright 1970-01-01 00:00:00 +0000
+++ copyright 2015-08-21 21:55:32 +0000
@@ -0,0 +1,16 @@
1Format: http://dep.debian.net/deps/dep5/
2
3Files: *
4Copyright: Copyright 2015, Canonical Ltd., All Rights Reserved.
5License: Apache License 2.0
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9 .
10 http://www.apache.org/licenses/LICENSE-2.0
11 .
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
017
=== renamed file 'copyright' => 'copyright.moved'
=== added file 'dist.yaml'
--- dist.yaml 1970-01-01 00:00:00 +0000
+++ dist.yaml 2015-08-21 21:55:32 +0000
@@ -0,0 +1,18 @@
1# This file contains values that are likely to change per distribution.
2# The aim is to make it easier to update / extend the charms with
3# minimal changes to the shared code in charmhelpers.
4packages:
5 - 'openjdk-7-jre'
6groups:
7 - 'hadoop'
8users:
9 flume:
10 groups: ['hadoop']
11dirs:
12 flume:
13 path: '/usr/lib/flume-syslog'
14 flume_conf:
15 path: '/etc/flume-syslog/conf'
16 flume_logs:
17 path: '/var/log/flume-syslog'
18 owner: 'flume'
019
=== renamed file 'dist.yaml' => 'dist.yaml.moved'
=== added directory 'hooks'
=== renamed directory 'hooks' => 'hooks.moved'
=== added file 'hooks/callbacks.py'
--- hooks/callbacks.py 1970-01-01 00:00:00 +0000
+++ hooks/callbacks.py 2015-08-21 21:55:32 +0000
@@ -0,0 +1,160 @@
1import os
2import re
3import signal
4from subprocess import Popen, check_output
5
6import jujuresources
7from charmhelpers.core import hookenv
8from charmhelpers.core import host
9from charmhelpers.core import unitdata
10from charmhelpers.core.charmframework.helpers import Relation
11from jujubigdata import utils
12from jujubigdata.relations import FlumeAgent
13
14
15# Extended status support
16# We call update_blocked_status from the "requires" section of our service
17# block, so be sure to return True. Otherwise, we'll block the "requires"
18# and never move on to callbacks. The other status update methods are called
19# from the "callbacks" section and therefore don't need to return True.
20def update_blocked_status():
21 if unitdata.kv().get('charm.active', False):
22 return True
23 if not FlumeAgent().connected_units():
24 hookenv.status_set('blocked', 'Waiting for relation to apache-flume-hdfs')
25 elif not FlumeAgent().is_ready():
26 hookenv.status_set('waiting', 'Waiting for Flume/HDFS to become ready')
27 return True
28
29
30def update_working_status():
31 if unitdata.kv().get('charm.active', False):
32 hookenv.status_set('maintenance', 'Updating configuration')
33 return
34 hookenv.status_set('maintenance', 'Setting up Flume/Syslog')
35
36
37def update_active_status():
38 unitdata.kv().set('charm.active', True)
39 hookenv.status_set('active', 'Ready')
40
41
42# Main Flume Syslog class for callbacks
43class Flume(object):
44 def __init__(self, dist_config):
45 self.dist_config = dist_config
46 self.resources = {
47 'flume': 'flume-%s' % host.cpu_arch(),
48 }
49 self.verify_resources = utils.verify_resources(*self.resources.values())
50
51 def is_installed(self):
52 return unitdata.kv().get('flume.installed')
53
54 def install(self, force=False):
55 if not force and self.is_installed():
56 return
57 jujuresources.install(self.resources['flume'],
58 destination=self.dist_config.path('flume'),
59 skip_top_level=True)
60 self.dist_config.add_users()
61 self.dist_config.add_dirs()
62 self.dist_config.add_packages()
63 self.setup_flume_config()
64 self.configure_flume()
65 unitdata.kv().set('flume.installed', True)
66
67 def setup_flume_config(self):
68 '''
69 copy the default configuration files to flume_conf property
70 defined in dist.yaml
71 '''
72 default_conf = self.dist_config.path('flume') / 'conf'
73 flume_conf = self.dist_config.path('flume_conf')
74 flume_conf.rmtree_p()
75 default_conf.copytree(flume_conf)
76 # Now remove the conf included in the tarball and symlink our real conf
77 default_conf.rmtree_p()
78 flume_conf.symlink(default_conf)
79
80 flume_env = self.dist_config.path('flume_conf') / 'flume-env.sh'
81 if not flume_env.exists():
82 (self.dist_config.path('flume_conf') / 'flume-env.sh.template').copy(flume_env)
83
84 flume_conf = self.dist_config.path('flume_conf') / 'flume.conf'
85 if not flume_conf.exists():
86 (self.dist_config.path('flume_conf') / 'flume-conf.properties.template').copy(flume_conf)
87
88 flume_log4j = self.dist_config.path('flume_conf') / 'log4j.properties'
89 utils.re_edit_in_place(flume_log4j, {
90 r'^flume.log.dir.*': 'flume.log.dir={}'.format(self.dist_config.path('flume_logs')),
91 })
92
93 def configure_flume(self):
94 flume_bin = self.dist_config.path('flume') / 'bin'
95 java_symlink = check_output(["readlink", "-f", "/usr/bin/java"])
96 java_home = re.sub('/bin/java', '', java_symlink).rstrip()
97 with utils.environment_edit_in_place('/etc/environment') as env:
98 if flume_bin not in env['PATH']:
99 env['PATH'] = ':'.join([env['PATH'], flume_bin])
100 env['FLUME_CONF_DIR'] = self.dist_config.path('flume_conf')
101 env['FLUME_CLASSPATH'] = self.dist_config.path('flume') / 'lib'
102 env['FLUME_HOME'] = self.dist_config.path('flume')
103 env['JAVA_HOME'] = java_home
104
105 def run_bg(self, user, command, *args):
106 """
107 Run a command as the given user in the background.
108
109 :param str user: User to run flume agent
110 :param str command: Command to run
111 :param list args: Additional args to pass to the command
112 """
113 parts = [command] + list(args)
114 quoted = ' '.join("'%s'" % p for p in parts)
115 e = utils.read_etc_env()
116 Popen(['su', user, '-c', quoted], env=e)
117
118 def restart(self):
119 # check for a java process with our flume dir in the classpath
120 if utils.jps(r'-cp .*{}'.format(self.dist_config.path('flume'))):
121 self.stop()
122 self.start()
123
124 def start(self):
125 # syslogudp needs to be run as root
126 self.run_bg(
127 'root',
128 self.dist_config.path('flume') / 'bin/flume-ng',
129 'agent',
130 '-c', self.dist_config.path('flume_conf'),
131 '-f', self.dist_config.path('flume_conf') / 'flume.conf',
132 '-n', 'a1')
133
134 def stop(self):
135 flume_pids = utils.jps(r'-cp .*{}'.format(self.dist_config.path('flume')))
136 for pid in flume_pids:
137 os.kill(int(pid), signal.SIGKILL)
138
139 def cleanup(self):
140 self.dist_config.remove_users()
141 self.dist_config.remove_dirs()
142
143
144class FlumeSyslog(Relation):
145 """
146 Relation which communicates ip / port data to syslog-related units.
147 """
148 relation_name = 'syslog'
149 required_keys = ['private-address', 'port']
150
151 def __init__(self, port=None, *args, **kwargs):
152 self.port = port # only needed for provides
153 super(FlumeSyslog, self).__init__(*args, **kwargs)
154
155 def provide(self, remote_service, all_ready):
156 data = super(FlumeSyslog, self).provide(remote_service, all_ready)
157 data.update({
158 'port': self.port,
159 })
160 return data
0161
=== added file 'hooks/common.py'
--- hooks/common.py 1970-01-01 00:00:00 +0000
+++ hooks/common.py 2015-08-21 21:55:32 +0000
@@ -0,0 +1,91 @@
1#!/usr/bin/env python
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13"""
14Common implementation for all hooks.
15"""
16
17import jujuresources
18from charmhelpers.core import hookenv
19from charmhelpers.core import unitdata
20from charmhelpers.core import charmframework
21
22
23def bootstrap_resources():
24 """
25 Install required resources defined in resources.yaml
26 """
27 if unitdata.kv().get('charm.bootstrapped', False):
28 return True
29 hookenv.status_set('maintenance', 'Installing base resources')
30 mirror_url = jujuresources.config_get('resources_mirror')
31 if not jujuresources.fetch(mirror_url=mirror_url):
32 missing = jujuresources.invalid()
33 hookenv.status_set('blocked', 'Unable to fetch required resource%s: %s' % (
34 's' if len(missing) > 1 else '',
35 ', '.join(missing),
36 ))
37 return False
38 jujuresources.install(['pathlib', 'jujubigdata'])
39 unitdata.kv().set('charm.bootstrapped', True)
40 return True
41
42
43def manage():
44 if not bootstrap_resources():
45 # defer until resources are available, since charmhelpers, and thus
46 # the framework, are required (will require manual intervention)
47 return
48
49 import jujubigdata
50 import callbacks
51
52 flume_reqs = ['packages', 'groups', 'users', 'dirs']
53 dist_config = jujubigdata.utils.DistConfig(filename='dist.yaml',
54 required_keys=flume_reqs)
55 flume = callbacks.Flume(dist_config)
56 manager = charmframework.Manager([
57 {
58 'name': 'flume',
59 'provides': [
60 # port is hard-coded to 514 because that's what rsyslog-forwarder
61 # expects. Make this a config opt once rsyslog-fwd supports
62 # changing this.
63 callbacks.FlumeSyslog(port='514'),
64 ],
65 'requires': [
66 flume.verify_resources,
67 jujubigdata.relations.FlumeAgent(),
68 callbacks.update_blocked_status, # not really a requirement, but best way to fit into framework
69 ],
70 'callbacks': [
71 callbacks.update_working_status,
72 flume.install,
73 charmframework.helpers.render_template(
74 source='flume.conf.j2',
75 target=flume.dist_config.path('flume_conf') / 'flume.conf',
76 context={'dist_config': dist_config}
77 ),
78 flume.restart,
79 callbacks.update_active_status,
80 ],
81 'cleanup': [
82 flume.stop,
83 flume.cleanup,
84 ],
85 },
86 ])
87 manager.manage()
88
89
90if __name__ == '__main__':
91 manage()
092
=== added file 'hooks/config-changed'
--- hooks/config-changed 1970-01-01 00:00:00 +0000
+++ hooks/config-changed 2015-08-21 21:55:32 +0000
@@ -0,0 +1,15 @@
1#!/usr/bin/env python
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14import common
15common.manage()
016
=== added file 'hooks/flume-agent-relation-changed'
--- hooks/flume-agent-relation-changed 1970-01-01 00:00:00 +0000
+++ hooks/flume-agent-relation-changed 2015-08-21 21:55:32 +0000
@@ -0,0 +1,15 @@
1#!/usr/bin/env python
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14import common
15common.manage()
016
=== added file 'hooks/install'
--- hooks/install 1970-01-01 00:00:00 +0000
+++ hooks/install 2015-08-21 21:55:32 +0000
@@ -0,0 +1,17 @@
1#!/usr/bin/python
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13import setup
14setup.pre_install()
15
16import common
17common.manage()
018
=== added file 'hooks/setup.py'
--- hooks/setup.py 1970-01-01 00:00:00 +0000
+++ hooks/setup.py 2015-08-21 21:55:32 +0000
@@ -0,0 +1,33 @@
1# Licensed under the Apache License, Version 2.0 (the "License");
2# you may not use this file except in compliance with the License.
3# You may obtain a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS,
9# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10# See the License for the specific language governing permissions and
11# limitations under the License.
12import subprocess
13from glob import glob
14
15
16def pre_install():
17 """
18 Do any setup required before the install hook.
19 """
20 install_pip()
21 install_bundled_resources()
22
23
24def install_pip():
25 subprocess.check_call(['apt-get', 'install', '-yq', 'python-pip', 'bzr'])
26
27
28def install_bundled_resources():
29 """
30 Install the bundled resources libraries.
31 """
32 archives = glob('resources/python/*')
33 subprocess.check_call(['pip', 'install'] + archives)
034
=== added file 'hooks/start'
--- hooks/start 1970-01-01 00:00:00 +0000
+++ hooks/start 2015-08-21 21:55:32 +0000
@@ -0,0 +1,15 @@
1#!/usr/bin/env python
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14import common
15common.manage()
016
=== added file 'hooks/stop'
--- hooks/stop 1970-01-01 00:00:00 +0000
+++ hooks/stop 2015-08-21 21:55:32 +0000
@@ -0,0 +1,15 @@
1#!/usr/bin/env python
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14import common
15common.manage()
016
=== added file 'hooks/syslog-relation-changed'
--- hooks/syslog-relation-changed 1970-01-01 00:00:00 +0000
+++ hooks/syslog-relation-changed 2015-08-21 21:55:32 +0000
@@ -0,0 +1,15 @@
1#!/usr/bin/env python
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14import common
15common.manage()
016
=== added file 'icon.svg'
--- icon.svg 1970-01-01 00:00:00 +0000
+++ icon.svg 2015-08-21 21:55:32 +0000
@@ -0,0 +1,863 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!-- Created with Inkscape (http://www.inkscape.org/) -->
3
4<svg
5 xmlns:dc="http://purl.org/dc/elements/1.1/"
6 xmlns:cc="http://creativecommons.org/ns#"
7 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8 xmlns:svg="http://www.w3.org/2000/svg"
9 xmlns="http://www.w3.org/2000/svg"
10 xmlns:xlink="http://www.w3.org/1999/xlink"
11 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
12 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
13 width="96"
14 height="96"
15 id="svg6517"
16 version="1.1"
17 inkscape:version="0.48.4 r9939"
18 sodipodi:docname="icon-template.svg">
19 <defs
20 id="defs6519">
21 <linearGradient
22 id="Background">
23 <stop
24 id="stop4178"
25 offset="0"
26 style="stop-color:#b8b8b8;stop-opacity:1" />
27 <stop
28 id="stop4180"
29 offset="1"
30 style="stop-color:#c9c9c9;stop-opacity:1" />
31 </linearGradient>
32 <filter
33 style="color-interpolation-filters:sRGB;"
34 inkscape:label="Inner Shadow"
35 id="filter1121">
36 <feFlood
37 flood-opacity="0.59999999999999998"
38 flood-color="rgb(0,0,0)"
39 result="flood"
40 id="feFlood1123" />
41 <feComposite
42 in="flood"
43 in2="SourceGraphic"
44 operator="out"
45 result="composite1"
46 id="feComposite1125" />
47 <feGaussianBlur
48 in="composite1"
49 stdDeviation="1"
50 result="blur"
51 id="feGaussianBlur1127" />
52 <feOffset
53 dx="0"
54 dy="2"
55 result="offset"
56 id="feOffset1129" />
57 <feComposite
58 in="offset"
59 in2="SourceGraphic"
60 operator="atop"
61 result="composite2"
62 id="feComposite1131" />
63 </filter>
64 <filter
65 style="color-interpolation-filters:sRGB;"
66 inkscape:label="Drop Shadow"
67 id="filter950">
68 <feFlood
69 flood-opacity="0.25"
70 flood-color="rgb(0,0,0)"
71 result="flood"
72 id="feFlood952" />
73 <feComposite
74 in="flood"
75 in2="SourceGraphic"
76 operator="in"
77 result="composite1"
78 id="feComposite954" />
79 <feGaussianBlur
80 in="composite1"
81 stdDeviation="1"
82 result="blur"
83 id="feGaussianBlur956" />
84 <feOffset
85 dx="0"
86 dy="1"
87 result="offset"
88 id="feOffset958" />
89 <feComposite
90 in="SourceGraphic"
91 in2="offset"
92 operator="over"
93 result="composite2"
94 id="feComposite960" />
95 </filter>
96 <clipPath
97 clipPathUnits="userSpaceOnUse"
98 id="clipPath873">
99 <g
100 transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)"
101 id="g875"
102 inkscape:label="Layer 1"
103 style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline">
104 <path
105 style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline"
106 d="m 46.702703,898.22775 50.594594,0 C 138.16216,898.22775 144,904.06497 144,944.92583 l 0,50.73846 c 0,40.86071 -5.83784,46.69791 -46.702703,46.69791 l -50.594594,0 C 5.8378378,1042.3622 0,1036.525 0,995.66429 L 0,944.92583 C 0,904.06497 5.8378378,898.22775 46.702703,898.22775 Z"
107 id="path877"
108 inkscape:connector-curvature="0"
109 sodipodi:nodetypes="sssssssss" />
110 </g>
111 </clipPath>
112 <filter
113 inkscape:collect="always"
114 id="filter891"
115 inkscape:label="Badge Shadow">
116 <feGaussianBlur
117 inkscape:collect="always"
118 stdDeviation="0.71999962"
119 id="feGaussianBlur893" />
120 </filter>
121 </defs>
122 <sodipodi:namedview
123 id="base"
124 pagecolor="#ffffff"
125 bordercolor="#666666"
126 borderopacity="1.0"
127 inkscape:pageopacity="0.0"
128 inkscape:pageshadow="2"
129 inkscape:zoom="3.4719894"
130 inkscape:cx="18.514671"
131 inkscape:cy="49.018169"
132 inkscape:document-units="px"
133 inkscape:current-layer="layer1"
134 showgrid="false"
135 fit-margin-top="0"
136 fit-margin-left="0"
137 fit-margin-right="0"
138 fit-margin-bottom="0"
139 inkscape:window-width="1366"
140 inkscape:window-height="744"
141 inkscape:window-x="0"
142 inkscape:window-y="24"
143 inkscape:window-maximized="1"
144 showborder="true"
145 showguides="true"
146 inkscape:guide-bbox="true"
147 inkscape:showpageshadow="false">
148 <inkscape:grid
149 type="xygrid"
150 id="grid821" />
151 <sodipodi:guide
152 orientation="1,0"
153 position="16,48"
154 id="guide823" />
155 <sodipodi:guide
156 orientation="0,1"
157 position="64,80"
158 id="guide825" />
159 <sodipodi:guide
160 orientation="1,0"
161 position="80,40"
162 id="guide827" />
163 <sodipodi:guide
164 orientation="0,1"
165 position="64,16"
166 id="guide829" />
167 </sodipodi:namedview>
168 <metadata
169 id="metadata6522">
170 <rdf:RDF>
171 <cc:Work
172 rdf:about="">
173 <dc:format>image/svg+xml</dc:format>
174 <dc:type
175 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
176 <dc:title></dc:title>
177 </cc:Work>
178 </rdf:RDF>
179 </metadata>
180 <g
181 inkscape:label="BACKGROUND"
182 inkscape:groupmode="layer"
183 id="layer1"
184 transform="translate(268,-635.29076)"
185 style="display:inline">
186 <path
187 style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline;filter:url(#filter1121)"
188 d="m -268,700.15563 0,-33.72973 c 0,-27.24324 3.88785,-31.13513 31.10302,-31.13513 l 33.79408,0 c 27.21507,0 31.1029,3.89189 31.1029,31.13513 l 0,33.72973 c 0,27.24325 -3.88783,31.13514 -31.1029,31.13514 l -33.79408,0 C -264.11215,731.29077 -268,727.39888 -268,700.15563 Z"
189 id="path6455"
190 inkscape:connector-curvature="0"
191 sodipodi:nodetypes="sssssssss" />
192 <image
193 y="651.29077"
194 x="-252"
195 id="image3185"
196 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKoAAACqCAYAAAA9dtSCAAAABHNCSVQICAgIfAhkiAAAIABJREFU
197eJzsvXm4JNdd3/2pravX233XWe7soxnNaF8sSxbGlrzIgA14CwlmkwEnhIAxAewkbwgxIQl23jyG
198hECAxDIxEDu2hTGWwbKRhCVb8iKNttln7sydmbtvfXvvqjrn5I/au/vOjORJ3lfPM795em7VqVOn
199zvKt33Z+55SmlOIqXaX/v5P+/3UFrtJVuhy6CtSr9Iqgq0C9Sq8IugrUq/SKoKtAvUqvCLoK1Kv0
200iqCrQL1Krwi6CtSr9Iqgq0C9Sq8IugrUq/SKoKtAvUqvCLoK1Kv0iqCrQL1Krwi6CtSr9Iqgq0C9
201Sq8IugrUq/SKoKtAvUqvCLoK1Kv0iqCrQL1Krwi6CtSr9Iqgq0C9Sq8IMv/vP1IihOJiq1+VkkgF
202oEDGeWV4XYh0fv8mlJKpdClVWGBURvTUIC08V1JGV5V/mZlVd7sOd2matkPTtHHT0G8xTH2fZVqj
203pmEUNA0TlSgTkOFzFBDUJ7wupJSuK9pd1612O+501/Ge9YS4IKWcdYV8fs+EcQilUCiUlAipkEKg
204lEIIgRQSqSRCSJSSfpqUCBlcC86lVEjpIYT0z4XAkxIpBVL4ZUrlX/PLDcvxz5WUeIk0JQRekC6C
2058oRM3B8cSymiZ6rgmpCS//6JT1wMEJdFGwJVSomu60Hn+2m6lhyQ9PnlkJQiBs8GFIFUyhSYZfBQ
2061TP4/j0qAoX/nBCg/n+9IPVBGQJSpQA1t+bdYxr6GzRN21vKZ27LWJntlmUUVIz5sBR63zXFxm1T
207CjRN0zOWUbAso1DMZyel5G6Arus5nU53ca7mHHJd76Tjim/tGBafVioElfKBKAPAKBWALgZDEkRS
2089qQn0yIgDQBbHwD9/CJ4tgpeEr/s4OUI8/edB/dIuWGfvBSKgJoCnlIRSGEwIMO0JKAHUXhdBB28
209EYUAlCIAzUVAmrpPprlrEqR9oI44dfhMH6QL6+JWQ9fvN03jtnIpfzBjmSMaaBGwB4D0ckmp/ty9
2103WBZZsYyjG3FQn6bUtDudOqrzc6/aHec59ud7oPbyt2/8LmpijiXDAGkguMQpAGwk5zO8+J0KT2k
211VCnwJkEaAjT5EsgBgO59Ruo4wWEvxZgul7TL34BC8nJU2rDyG5FSEiRIH1lBWkLUDwBozBkHgDTB
212RVNcdwAXXaypn8tYxt+3LPN62zJHQdOTsAqPdA10XWIYoOv+Twv+xu1I1GPQCxUgVgiFFApPgOdB
21311G4QvMBrRJtD1STZqtTazTbp5ut9qOjmfqvSOEFHFakxXAPaHq5aySee7mmCLihDFSKgGuHYJUJ
214LpoU7ZF47y0z4Na++uGX/eef+vSG43+5lADqBkD0ZdbLKtyvrLhoHiElRECOxenLEvVBfVMgVTLF
2151ZSSLNfkb2Wz9t+zLXOnrut2Woz7B4YBliUxTI2NBUYC1GG9NwJp4m98pwIUUoDnKrpdRaur43lx
216OVL6dfaE8NZrzfl6o/WNaq3xq1sLjfNKCDypkMKLOVkASs8LRXWo4wY6q4jFcghOH4CiH3ApLjuA
217cwZ6a5qL9qsDn/7sZzfqwMuml8BR+2kjPVVK2Sdmeympi/rnCS6qVEq3SXNGkSgjAbCBBlMM0rlV
218J2uaxj/PZzPvy1jmhKbpRrJ0pXxw2rYPzv4n97Wgpz2DQRrXczBIe8tUCjxX4jiKal3H9fy+8stX
219CE/KZqtdW15b/+p6rf7LmzJrF2LgSEQA2hRwNzB+Qp1VBUANQZsS6xsZTqFBJiSeFCipEiBNGnWC
220zzz4Fxfpx8ujS1r9F9NBB4JUXVrU+5axtqHBJJVEo38YpRARc09a9P6fflGvgPk1d1jXeftQMfdb
221dsba0isedB0yGYFp6fgX/P9fyusrLtNg6Fcq0ueh6DdNMEyNXF7RaUtW1zW6jp9H03W9UCxUcvnc
222u4fLpfvmFjOfqHda/35cX5rvFf2RtR4Az+euSYMorR6E1n6YL+a+g0EqeoynSBWQIadVF8XCS6GY
223o74UES8l/fJQIpWOFN6Gt23ERSHQyQZw0bh+8T29XHSQLnp+uWtYpv6anJ35vVw2c6OmpStsGIpM
224RmKag9vcw5s3ziEllxoKlapnqrYkQRoU2N92oNuRLK1Bp+vr8yGopYTVterc/MLib3Y6nU8Ps7iW
225FOUXcztJEeaTAYOJdVDRA+AI1En9OABz0nCK3FQydLEJvvDFhy7RQ5em70r0+ySRYmOxBwmA+icp
226Md3rG1XpG1OGVATSQRZ9kF8qxfyau8fOmP8ql838iGmYuWSWEKCWpfVZ31Ex/SUPzBW+FBcDalLs
22797uv/MbEvEKhEQM65QoL/nbaksVVaHdDdSNUCYS6MDv3+Npa9cNF59wjffrnIAtfSqQnYn01yWF7
2289MxeP2koOWMjbICRpXyu+sUvfekSfXlp2kD0+4bVpXylUsXupI3oolwUUs77jXRRCPRetMG6KLGo
229X6i678xnM/82n8seSN6fBGgo3l8uheJM4+IgTdKlQNp/rffMb3fGhm1b/LRqVTK/qhO4E7VtW7e+
230rpgvfHZmVvvNeqvzX8tiupN0OyUNpF5facrt1SfeReDSCj0O/YZTBNLwHiVRUiEuYUxfLg3mqJeh
231BmzkdhJSYgRSVgVvVFhmCqRJt5NSqMTzkrNEYd7eMmJm43PR2RUnm7GM/1jMZ3/SNM1ieFnXfYBm
232Mun2vFxu6tcl0BdRL0Hs94r8fm+Az03TqoCKAN0PbKkknbZkdkmj3fFLlQocxxHnL1z46tpa9dey
233zVMvpAwoLwTnRrNLab9ppC4EYxkCWMm0jhqpAUG+UOwrqfjyV796iV66NKU4amQ49YG0x3W1AUgh
2345sBCyj4x79+qAsaYEOnB8y5nhik53GEd5ladsXwu8xeFnH13UhfNZBTZbGC4hc+6mCdi40uJ+sSg
235uhT1WvvJpyTF/UbPVwmA9oI07Ak7p7F7O6yv+4D1pMIwTWPHjp1vse3s/rk5+YvG2tGHRKhDJtSB
236yKU0wLEfAk0ElvsgkCoVct9egMYc9UoZUymgbjzDFKd73sbGUki+E3+w28nX7dKD0wvQpOP7YlwU
237YH7NuatYyP1Jzs7sj9uhsG2FZfXW65JV5+JwTV+7lG4a3xUp6FE90pMY/dfjMgZP1cbSyP9vqKxh
238mJIL89Dq+px1bHxit2FZnzyP9hty4dn/HInyi3DTlGcg0F1DEa4C0IaiXab0VZXSU5NpV4IuOyjF
239k0nHfD9FU6ByABeFvhmmlGW7gcHUy0UloCcMs/k158eKhdx/zGasTWGJuu77Qn1d9HLBeTkiP67j
240pbjpYANVMYiLblSbVHBL0vOqfLUokRwcS/J52L9HMb+omFnSUEoxNFQZ3rXL+si0pu+u15u/Zq0+
241LwZa9L1GVsI3GnHjBFhjgysAaK/oTxhbV4IuC6ieJ7jYIF7KeX8xAyjmIhKltLDAPjGPUmjK1wmV
242Uiyui18ZKhZ+PWMZ5TBLJqOwbYCNLfqB9e+r2eAcSRrU/b0AjHXTBHft844M4rbpe8Krg0Hqv+hJ
243g2vTOJim4Ny8jucq7Fwut3PX3l9UZ0+PV919/0Qtv1gLAaiCef/0DFNgPEmR4JIq8gAopSJwRyCV
244MUBDtUAGPvErQWaolw5y7F82F90IpBtMgUJaJPiDo5F0O0XXZPr++dWurunGvygVcx+yDKMY2n3Z
245bL+ovxy6OEiDtiRUlcvRTQeWlERXcKQlQNrviorvkUk9Nbg5ytXbX0FBwxUwNI+pWY22A0YmY+7Y
246fc17pFKFVXHd++TicysbOe9jEIfHoViPfaVJjhmrBwmASh/QVwyoITiTIJU9HHIQXVrUx7NOG4H0
247krpo77EUaLr+z0uF3D+zDL0ACk3TyOYU1kuMrN3YhNkoLQZWH08cwL5VwnEflrlhf/TopPEvWXaS
248kyoifT9Rjoxeaj+1VNbYrUmmLkCjo6Hppr591zU/LIRkTVx/v5g75HPWlOM+7cAXMj09KpSEkLsG
249AO01pMLZx3B26kpQn/UUWoYXA2mom0ghUwCTxL7RUHT3Ai3NSYMcvSAN9NakfqOkZGFd/EKxkPtn
250lqkXADRNw7bFSwJpjyDeIEdMl46fvVQZvda6T1qPJR8ZTr3pYRnRScJVlahDDNIwzR+bUhH2bFPk
251bQFKouuGvm3n3h8qlkd+n4mbLU8KhOd7ATzhRVOtccxpfBzOdnnCi8IMReSHFXgy4M6hvhtcvxKU
252ikdV8tIxo6kZJnpFfXrunkAup3XRSweSDIoZnVvzfniolP83lmkUFaAHIM1kLh56OLg1Fxf1IQ0S
253+SlbfWAxg6ZLB+jcxNOg0XnPayST4FX+00N1QEV5ZDwWUblJNUxRKCj2blOcmFbU2hqabhqTu/b9
254/a7TXWgL8Suyx4qPuGJPulIq4r5JHTTUW0PXVZTei4fvghLy/uKF+j4z5XPaIK8KjJskFw07TEEf
255SH1lOyqwD6TJF0Ep5c9OKcmFFfdAMZ/7/YxlVsD3itq2wMroKUE56EeqRr08PtXC1NmlQTqorCTU
256whezv3RtIEiTZfeqAWF8ajpvCNIop5IpkKqEflsowt7tklxGIAHLypjbd1/786U9r32fSHBVX6QH
25758HfELye8M+j2ScZxxNEvtnQrRUtg7lixtSlo7BD573WI+b9g410UVLToBePvE9znCS4zy0724r5
2587Gds29oaZg9BujHo+mlttUp1rdaXXijmMQwDy7IYKhfSdWVjvbSfAsAkAJw2huKy0hMBSe4bAzhS
259AYJLyVmrSPwn+0wlpVbAhxMqggrUgH07FIenBG1Hx87mstt27f+o57oLK8ce/UIYcKKkRKiEoz/J
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
356Q6ASapoP0JCLhtL3CoHVTG25k8RgstJwUYs+aeEldVHoBalfhmWaP+wGwcy2Ba22Q63ti9GV9Tau
357FyxLyRh4ukahkmW26bIpZyFH85w+s4bn+fkXrYOs65vY1n2KrCmxDY2OKyLdUypFy/VYa0ElawR1
358S64P6/G1RktzJEg48cQj2NYM2QI8MnuQt//kD71kMf1/kq7fO8r1e9PG1xPPnBzIRZN/eym+3p82
359WlZwPrpwWwTSQAeFWB+FaOh97nqFkGr2gTQJNgaDtF+M+DmTxpOfohJcV/GZr69/cLxS+Plt44Vx
360O5NhbqlBq5ueqXG94GNoChwhyY3mUBIMNGpNl9mZdRxXUCmaNDsK11O09WHq+laGxBkm8hkU0HY9
361Oq5HreOglKLa6aJpFpamYWoaZuDvkDKxgYOM3VZuu8HazAnW5s6i6/C82sff+9H/8yAVbova9GPk
362Jm4kO7T9ZZUxXim9ZC46CKAhlYuSxHcQDkbjHHBRpWk+SEO/NcmgyytDZlLUE0UKhRX2A2Cj0KSA
363Q4Uuh8jtdMlVj4pPPrJ8+w17N/+bkXI2MzFsMzW7jutJLEOP1islpDATI3kqQxkcCVlLp153OH56
364FaUUQ3kLISTbxrNMzXaQKCyxTuwXVWR1Dds2MfCXjSilWG12/TxBeF5G19hashMg9dO9Tpu1C8ep
365zp0G4KSzhbvf8pYrBtLmwnN01k5R2fv9GFY+Sm+tnGD95P9kaPJ2WnPfftlALRayrK+2GBr2/cIv
366F6BhWikHEfSU2qkpBXoQNKSFn1QK45nVd/lxpMGkpwym5HHoJ40qErgctHATA188hmFeobiMuGi0
367+4lfbjZjvjGTsTJCKGqt2FoOVYDEZiEoFKalYw/nMA0N1RVcOLsW1aHadKm2XByhKBX8WRpduST9
368pv5aeD86fzRrBXUOdStf+e+4HivNbgzSoCLLZ56jOj+FlJIWWTbf8kbedd91AzvQbS8j3NbAaxtR
369e+kZMlmd6qm/AqBTO8/cUx+mu/Q4w7u/FyOTR8lLlyncFvULT/alv/HufTz20LeorbUvYizFIB3k
370U03+bFuRuGHc557S10lDXEQmXHwE2sDnvxzSk34wv5KJiJewIgnREW5/+Cdfmb/94UPtw595ovqR
371foMpXiclAxAXcvabAMYrNqsJPTTkolpCfZAKml1/Db2hadTXu7heaJ2DaWiMlmzytkmr46GLNpao
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
436zs3XefH0KqfPrzO31GJ2toHr+jNP4UREV0gMDYZLWdabDh3XAXQmRwt0HcHoUI5Nw3l0JLNNh6pW
4374tvF9/T1wria46nn4h2srdwYpT3vpD73wiV70G2v01x4FssyyA+NM7rjVanr9aUpzh59kqqYTHHP
438EWuR/Xe/n+vf+Jtcc+u72bvvVWS1KgBNNnF2rs3sicdp1xZp1xapL03hdptxwQqcrovT6WJmiozu
439uB2nMUu3tYoMVtS6XQcjO0Jr+eRF27B3sszCycOcW1xi3HC5oZKhKxSn1h00s4xCMVfLs2fXNraN
440DtHKV5p/cb75G3814wN7od5lOGf9xlK1/ahlaH/x5ePLzx79wK3DP/emHf/68enGrkt04S3HlruP
441fvyFtUf/w3eW//XDU/UHnjjXvD9x/Z5n51tnICH6Q+o1mG6+ZujTz51pfVAAjY6LkpnETsO+Tisk
442t06vWrdPDrWfjj+iJaO9icJPaT9ywrx9cmLicwf2jE0I6dHqCMbKNicu1MlmdJTSmBjOc2GpQd42
4436XoSIUEaOt2OIF+2sXSNs3WHrGnQWmwzvdJhvdmmmLVod106rsnWiSGmFlosVWs8e34l+ijaC9ZB
444dubuZXv70XigzDm+9OUnuevmd0Vp2aHtsOed1Kce7JsmTZLvfFcbWvZz00epsy3Oj0PRbLL11n+M
445lRujPvMUbtvnhGPlIh3Xo1CaQDezLMw8x8qJeDJiU2WBLde8BgDPE7RbHd/aD2h48maWpp4iO7wP
446hY2UCjNboFubp3r6PGBR2HwrViFWc5RU2Lqg1aiR0RVoGuuuxPUkZ2eafH16C46zhddvH+KUWUOr
447THA+40aNNTCZb3iP/cGP77/3g8Ruqf/8Hnh8unHPNSOZR//s8NqzwL1Atbd/Hjy+/kuOVPfsKlnk
448Te2epieZbXn3mzN8rGKbzy63vHsOjtlVAD0ZM5r8Qkro/Bee97vbJ4oU8ha7d4y8ygu/ICxiAK7W
449OrXd20b+ixAC1w2++e550deIPSF45Lhx+4G9u74xOjqy0zRguGSDrtPq+h6HZkdgmf4EwI17R+i4
450AscVtDsuZtbE02C1Kzi+3qUrFQ1XcH6xjeMIRoay1FoO622HarNLoWxTq9j8zYsrqNo8N7pH2eed
451BeCJ3Fv6VADP6fSBLDu0ncL276cdWNeDSDcsrOIkazPPD7yuEjtll8wau3YdZPedP092aDurp76E
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
783"
784 height="63.999981"
785 width="64" />
786 </g>
787 <g
788 inkscape:groupmode="layer"
789 id="layer3"
790 inkscape:label="PLACE YOUR PICTOGRAM HERE"
791 style="display:inline" />
792 <g
793 inkscape:groupmode="layer"
794 id="layer2"
795 inkscape:label="BADGE"
796 style="display:none"
797 sodipodi:insensitive="true">
798 <g
799 style="display:inline"
800 transform="translate(-340.00001,-581)"
801 id="g4394"
802 clip-path="none">
803 <g
804 id="g855">
805 <g
806 inkscape:groupmode="maskhelper"
807 id="g870"
808 clip-path="url(#clipPath873)"
809 style="opacity:0.6;filter:url(#filter891)">
810 <path
811 transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-237.54282)"
812 d="m 264,552.36218 c 0,6.62742 -5.37258,12 -12,12 -6.62742,0 -12,-5.37258 -12,-12 0,-6.62741 5.37258,-12 12,-12 6.62742,0 12,5.37259 12,12 z"
813 sodipodi:ry="12"
814 sodipodi:rx="12"
815 sodipodi:cy="552.36218"
816 sodipodi:cx="252"
817 id="path844"
818 style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
819 sodipodi:type="arc" />
820 </g>
821 <g
822 id="g862">
823 <path
824 sodipodi:type="arc"
825 style="color:#000000;fill:#f5f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
826 id="path4398"
827 sodipodi:cx="252"
828 sodipodi:cy="552.36218"
829 sodipodi:rx="12"
830 sodipodi:ry="12"
831 d="m 264,552.36218 c 0,6.62742 -5.37258,12 -12,12 -6.62742,0 -12,-5.37258 -12,-12 0,-6.62741 5.37258,-12 12,-12 6.62742,0 12,5.37259 12,12 z"
832 transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-238.54282)" />
833 <path
834 transform="matrix(1.25,0,0,1.25,33,-100.45273)"
835 d="m 264,552.36218 c 0,6.62742 -5.37258,12 -12,12 -6.62742,0 -12,-5.37258 -12,-12 0,-6.62741 5.37258,-12 12,-12 6.62742,0 12,5.37259 12,12 z"
836 sodipodi:ry="12"
837 sodipodi:rx="12"
838 sodipodi:cy="552.36218"
839 sodipodi:cx="252"
840 id="path4400"
841 style="color:#000000;fill:#dd4814;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
842 sodipodi:type="arc" />
843 <path
844 sodipodi:type="star"
845 style="color:#000000;fill:#f5f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
846 id="path4459"
847 sodipodi:sides="5"
848 sodipodi:cx="666.19574"
849 sodipodi:cy="589.50385"
850 sodipodi:r1="7.2431178"
851 sodipodi:r2="4.3458705"
852 sodipodi:arg1="1.0471976"
853 sodipodi:arg2="1.6755161"
854 inkscape:flatsided="false"
855 inkscape:rounded="0.1"
856 inkscape:randomized="0"
857 d="m 669.8173,595.77657 c -0.39132,0.22593 -3.62645,-1.90343 -4.07583,-1.95066 -0.44938,-0.0472 -4.05653,1.36297 -4.39232,1.06062 -0.3358,-0.30235 0.68963,-4.03715 0.59569,-4.47913 -0.0939,-0.44198 -2.5498,-3.43681 -2.36602,-3.8496 0.18379,-0.41279 4.05267,-0.59166 4.44398,-0.81759 0.39132,-0.22593 2.48067,-3.48704 2.93005,-3.4398 0.44938,0.0472 1.81505,3.67147 2.15084,3.97382 0.3358,0.30236 4.08294,1.2817 4.17689,1.72369 0.0939,0.44198 -2.9309,2.86076 -3.11469,3.27355 -0.18379,0.41279 0.0427,4.27917 -0.34859,4.5051 z"
858 transform="matrix(1.511423,-0.16366377,0.16366377,1.511423,-755.37346,-191.93651)" />
859 </g>
860 </g>
861 </g>
862 </g>
863</svg>
0864
=== renamed file 'icon.svg' => 'icon.svg.moved'
=== added file 'metadata.yaml'
--- metadata.yaml 1970-01-01 00:00:00 +0000
+++ metadata.yaml 2015-08-21 21:55:32 +0000
@@ -0,0 +1,13 @@
1name: apache-flume-syslog
2summary: Ingest syslog events with Apache Flume
3maintainer: Kevin Monroe <kevin.monroe@canonical.com>
4description: |
5 Uses a Syslog source, memory channel, and Avro sink in Apache Flume
6 to ingest log data.
7tags: ["applications", "bigdata", "apache"]
8provides:
9 syslog:
10 interface: syslog
11requires:
12 flume-agent:
13 interface: flume-agent
014
=== renamed file 'metadata.yaml' => 'metadata.yaml.moved'
=== added directory 'resources'
=== renamed directory 'resources' => 'resources.moved'
=== added file 'resources.yaml'
--- resources.yaml 1970-01-01 00:00:00 +0000
+++ resources.yaml 2015-08-21 21:55:32 +0000
@@ -0,0 +1,12 @@
1options:
2 output_dir: /home/ubuntu/resources
3resources:
4 pathlib:
5 pypi: path.py>=7.0
6 jujubigdata:
7 pypi: jujubigdata>=4.0.0,<5.0.0
8optional_resources:
9 flume-x86_64:
10 url: https://git.launchpad.net/bigdata-data/plain/apache/x86_64/apache-flume-1.6.0-bin.tar.gz?id=c34a21c939f5fce9ab89b95d65fe2df50e7bbab0
11 hash: defd21ad8d2b6f28cc0a16b96f652099
12 hash_type: md5
013
=== renamed file 'resources.yaml' => 'resources.yaml.moved'
=== added directory 'resources/python'
=== added file 'resources/python/PyYAML-3.11.tar.gz'
1Binary files resources/python/PyYAML-3.11.tar.gz 1970-01-01 00:00:00 +0000 and resources/python/PyYAML-3.11.tar.gz 2015-08-21 21:55:32 +0000 differ14Binary files resources/python/PyYAML-3.11.tar.gz 1970-01-01 00:00:00 +0000 and resources/python/PyYAML-3.11.tar.gz 2015-08-21 21:55:32 +0000 differ
=== added file 'resources/python/charmhelpers-0.3.1.tar.gz'
2Binary files resources/python/charmhelpers-0.3.1.tar.gz 1970-01-01 00:00:00 +0000 and resources/python/charmhelpers-0.3.1.tar.gz 2015-08-21 21:55:32 +0000 differ15Binary files resources/python/charmhelpers-0.3.1.tar.gz 1970-01-01 00:00:00 +0000 and resources/python/charmhelpers-0.3.1.tar.gz 2015-08-21 21:55:32 +0000 differ
=== added file 'resources/python/jujuresources-0.2.9.tar.gz'
3Binary files resources/python/jujuresources-0.2.9.tar.gz 1970-01-01 00:00:00 +0000 and resources/python/jujuresources-0.2.9.tar.gz 2015-08-21 21:55:32 +0000 differ16Binary files resources/python/jujuresources-0.2.9.tar.gz 1970-01-01 00:00:00 +0000 and resources/python/jujuresources-0.2.9.tar.gz 2015-08-21 21:55:32 +0000 differ
=== added file 'resources/python/pyaml-15.5.7.tar.gz'
4Binary files resources/python/pyaml-15.5.7.tar.gz 1970-01-01 00:00:00 +0000 and resources/python/pyaml-15.5.7.tar.gz 2015-08-21 21:55:32 +0000 differ17Binary files resources/python/pyaml-15.5.7.tar.gz 1970-01-01 00:00:00 +0000 and resources/python/pyaml-15.5.7.tar.gz 2015-08-21 21:55:32 +0000 differ
=== added file 'resources/python/six-1.9.0-py2.py3-none-any.whl'
5Binary files resources/python/six-1.9.0-py2.py3-none-any.whl 1970-01-01 00:00:00 +0000 and resources/python/six-1.9.0-py2.py3-none-any.whl 2015-08-21 21:55:32 +0000 differ18Binary files resources/python/six-1.9.0-py2.py3-none-any.whl 1970-01-01 00:00:00 +0000 and resources/python/six-1.9.0-py2.py3-none-any.whl 2015-08-21 21:55:32 +0000 differ
=== added directory 'templates'
=== renamed directory 'templates' => 'templates.moved'
=== added file 'templates/flume.conf.j2'
--- templates/flume.conf.j2 1970-01-01 00:00:00 +0000
+++ templates/flume.conf.j2 2015-08-21 21:55:32 +0000
@@ -0,0 +1,28 @@
1# list sources, sinks, and channels in the agent
2a1.sources = r1
3a1.sinks = k1
4a1.channels = c1
5
6# source properties
7a1.sources.r1.type = {{ config['source_type'] }}
8a1.sources.r1.channels = c1
9a1.sources.r1.host = 0.0.0.0
10a1.sources.r1.keepFields = true
11a1.sources.r1.port = {{ config['source_port'] }}
12
13# inject our configured subdir
14a1.sources.r1.interceptors = i1
15a1.sources.r1.interceptors.i1.type = static
16a1.sources.r1.interceptors.i1.key = event_dir
17a1.sources.r1.interceptors.i1.value = {{ config['event_dir'] }}
18
19# channel properties
20a1.channels.c1.type = memory
21a1.channels.c1.capacity = {{ config['channel_capacity'] }}
22a1.channels.c1.transactionCapacity = {{ config['channel_transaction_capacity'] }}
23
24# sink properties
25a1.sinks.k1.type = {{ any_ready_unit('flume-agent')[1]['protocol'] }}
26a1.sinks.k1.channel = c1
27a1.sinks.k1.hostname = {{ any_ready_unit('flume-agent')[1]['private-address'] }}
28a1.sinks.k1.port = {{ any_ready_unit('flume-agent')[1]['port'] }}
029
=== added directory 'tests'
=== renamed directory 'tests' => 'tests.moved'
=== added file 'tests/00-setup'
--- tests/00-setup 1970-01-01 00:00:00 +0000
+++ tests/00-setup 2015-08-21 21:55:32 +0000
@@ -0,0 +1,5 @@
1#!/bin/bash
2
3sudo add-apt-repository ppa:juju/stable -y
4sudo apt-get update
5sudo apt-get install python3 amulet -y
06
=== added directory 'tests/remote'
=== added file 'tests/remote/test_dist_config.py'
--- tests/remote/test_dist_config.py 1970-01-01 00:00:00 +0000
+++ tests/remote/test_dist_config.py 2015-08-21 21:55:32 +0000
@@ -0,0 +1,62 @@
1#!/usr/bin/env python
2
3import grp
4import pwd
5import unittest
6
7from charmhelpers.contrib import bigdata
8
9
10class TestDistConfig(unittest.TestCase):
11 """
12 Test that the ``dist.yaml`` settings were applied properly, such as users, groups, and dirs.
13
14 This is done as a remote test on the deployed unit rather than a regular
15 test under ``tests/`` because filling in the ``dist.yaml`` requires Juju
16 context (e.g., config).
17 """
18 @classmethod
19 def setUpClass(cls):
20 cls.hadoop = bigdata.handlers.apache.HadoopBase()
21
22 def test_groups(self):
23 for name in self.hadoop.groups:
24 try:
25 grp.getgrnam(name)
26 except KeyError:
27 self.fail('Group {} is missing'.format(name))
28
29 def test_users(self):
30 for username, details in self.hadoop.users.items():
31 try:
32 user = pwd.getpwnam(username)
33 except KeyError:
34 self.fail('User {} is missing'.format(username))
35 for groupname in details['groups']:
36 try:
37 group = grp.getgrnam(groupname)
38 except KeyError:
39 self.fail('Group {} referenced by user {} does not exist'.format(
40 groupname, username))
41 if group.gr_gid != user.pw_gid:
42 self.assertIn(username, group.gr_mem, 'User {} not in group {}'.format(
43 username, groupname))
44
45 def test_dirs(self):
46 for name, details in self.hadoop.managed_dirs.items():
47 dirpath = details['path']
48 self.assertTrue(dirpath.isdir(), 'Dir {} is missing'.format(name))
49 stat = dirpath.stat()
50 owner = pwd.getpwuid(stat.st_uid).pw_name
51 group = grp.getgrgid(stat.st_gid).gr_name
52 perms = stat.st_mode & ~0o40000
53 self.assertEqual(owner, details.get('owner', 'root'),
54 'Dir {} ({}) has wrong owner: {}'.format(name, dirpath, owner))
55 self.assertEqual(group, details.get('group', 'root'),
56 'Dir {} ({}) has wrong group: {}'.format(name, dirpath, group))
57 self.assertEqual(perms, details.get('perms', 0o744),
58 'Dir {} ({}) has wrong perms: 0o{:o}'.format(name, dirpath, perms))
59
60
61if __name__ == '__main__':
62 unittest.main()

Subscribers

People subscribed via source and target branches