Merge lp:~axwalk/juju-core/lp1281071-rsyslog-tls into lp:~go-bot/juju-core/trunk
- lp1281071-rsyslog-tls
- Merge into trunk
Status: | Merged |
---|---|
Merge reported by: | John A Meinel |
Merged at revision: | not available |
Proposed branch: | lp:~axwalk/juju-core/lp1281071-rsyslog-tls |
Merge into: | lp:~go-bot/juju-core/trunk |
Diff against target: |
2006 lines (+660/-331) 45 files modified
agent/agent.go (+0/-1) cmd/juju/environment_test.go (+0/-1) cmd/jujud/machine.go (+16/-10) cmd/jujud/machine_test.go (+27/-0) cmd/jujud/unit.go (+4/-0) container/testing/common.go (+0/-1) environs/cloudinit.go (+0/-10) environs/cloudinit/cloudinit.go (+0/-40) environs/cloudinit/cloudinit_test.go (+13/-33) environs/cloudinit_test.go (+0/-5) environs/config/config.go (+20/-4) environs/config/config_test.go (+0/-9) log/syslog/config.go (+46/-14) log/syslog/config_test.go (+12/-0) log/syslog/testing/syslogconf.go (+21/-4) provider/azure/customdata_test.go (+0/-2) provider/local/config.go (+0/-1) provider/local/environ.go (+9/-6) provider/local/environprovider.go (+6/-7) state/address.go (+0/-2) state/api/params/params.go (+5/-2) state/api/provisioner/provisioner_test.go (+0/-1) state/api/rsyslog/package_test.go (+14/-0) state/api/rsyslog/rsyslog.go (+44/-0) state/api/rsyslog/rsyslog_test.go (+33/-0) state/api/state.go (+6/-0) state/apiserver/deployer/deployer.go (+0/-1) state/apiserver/provisioner/provisioner.go (+0/-1) state/apiserver/provisioner/provisioner_test.go (+0/-1) state/apiserver/root.go (+12/-0) state/apiserver/rsyslog/package_test.go (+14/-0) state/apiserver/rsyslog/rsyslog.go (+56/-0) state/apiserver/rsyslog/rsyslog_test.go (+48/-0) upgrades/export_test.go (+0/-2) upgrades/rsyslogconf.go (+0/-50) upgrades/rsyslogconf_test.go (+0/-72) upgrades/steps118.go (+0/-10) upgrades/steps118_test.go (+1/-3) worker/deployer/export_test.go (+2/-3) worker/deployer/simple.go (+1/-18) worker/deployer/simple_test.go (+4/-13) worker/provisioner/kvm-broker.go (+0/-1) worker/provisioner/lxc-broker.go (+0/-1) worker/provisioner/lxc-broker_test.go (+1/-2) worker/rsyslog/worker.go (+245/-0) |
To merge this branch: | bzr merge lp:~axwalk/juju-core/lp1281071-rsyslog-tls |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+207889@code.launchpad.net |
Commit message
Description of the change
Implement rsyslog TLS support
This changes the rsyslog configuration
we generate to use TLS. We install the
rsyslog-gnutls package and generate a
new CA cert, server cert and key
specifically for rsyslog.
This completely changes the way rsyslog
configuration is managed. Now, instead
of writing at bootstrap time and having
an upgrade step, we have a worker that
writes the syslog config whenever syslog
parameters change. The state server will
generate certificates and propagate the
CA cert to other agents via environ config.
There are some other miscellaneous changes:
- we now use reliable forwarding, as
otherwise the machine agent and unit
agent will restart rsyslog while
log messages are buffered causing
message loss
- dedicated upgrades for rsyslog are
redundant and removed. The new worker
upgrades machine and unit agent rsyslog
automatically.
- syslog-port can now be changed, and must
be changed to work around the privilege
drop race in rsyslog 5.x (this is the
sole motivation)
- the ryslog config path is no longer
populated into agent.conf, and we
no longer use the existing value to
perform cleanups. The worker is now
responsible for cleaning up the config
file on tear-down.
- the local provider symlinks machine-0.log
into /var/log/
do not need any configuration other than
the existing namespace to determine log
location
TODO(axw) tests in worker/rsyslog
TODO(axw) tests in state/api/rsyslog
TODO(axw) tests in state/apiserver
Fixes lp:1281071
Andrew Wilkins (axwalk) wrote : | # |
Tim Penhey (thumper) wrote : | # |
We already need to rewrite the syslog config files as part of the 1.18
upgrade process as they are all out of date and wrong, so this is
something we need to address anyway.
I'd like to see us move from UDP to TCP for the logging.
I'm a little surprised that I have never been hit by the inability for a
machine to listen on the current port.
https:/
File environs/
https:/
environs/
path.Join(
Do we really want to reuse the same cert? I strongly suggest that we
have different certs / keys for different jobs.
https:/
File log/syslog/
https:/
log/syslog/
Argh... you can't just change this.
rsyslog has an apparmor profile that restricts where it can write files.
This was a source of many hours of searching.
Needs to be /var/log/** somewhere.
https:/
log/syslog/
I think we should actually be using TCP not UDP for log messages anyway.
There is a built in store and forward mechanism.
https:/
log/syslog/
Why had I not been hit by this port number problem?
https:/
log/syslog/
If we switch to TCP for all, we can avoid this.
https:/
File log/syslog/
https:/
log/syslog/
/var/log/
Oh? so this isn't the same as the mongo cert?
Andrew Wilkins (axwalk) wrote : | # |
I'll start on a new worker, and do the certificate stuff at the same
time.
If we don't mind installing rsyslog-gnutls on machine-0 for local, we
can remove the syslog-tls config attr and make TLS mandatory.
https:/
File environs/
https:/
environs/
path.Join(
On 2014/02/24 21:48:29, thumper wrote:
> Do we really want to reuse the same cert? I strongly suggest that we
have
> different certs / keys for different jobs.
I will update the code to generate a new CA cert/key for rsyslog, and
use that to sign a new server cert. The CA cert will be populated into
environment config, which the rsyslog worker will watch for.
https:/
File log/syslog/
https:/
log/syslog/
On 2014/02/24 21:48:29, thumper wrote:
> Argh... you can't just change this.
I tested it and it works on both precise and trusty.
> rsyslog has an apparmor profile that restricts where it can write
files. This
> was a source of many hours of searching.
I know, and I did it knowingly. It is writing to /var/log/juju, on
account of the symlink.
> Needs to be /var/log/** somewhere.
If we hard-code it, then the SyslogConfig parameters ought to be
changed. Otherwise it looks like it's going to write to the configured
log-dir, but doesn't.
https:/
log/syslog/
On 2014/02/24 21:48:29, thumper wrote:
> I think we should actually be using TCP not UDP for log messages
anyway. There
> is a built in store and forward mechanism.
Probably not a bad idea, but let's please leave that until after TLS is
sorted.
https:/
log/syslog/
On 2014/02/24 21:48:29, thumper wrote:
> Why had I not been hit by this port number problem?
I don't know the specifics of the bug. All I know is that it only hit me
when I was using TLS, and not UDP.
https:/
File log/syslog/
https:/
log/syslog/
/var/log/
On 2014/02/24 21:48:29, thumper wrote:
> Oh? so this isn't the same as the mongo cert?
It is, it's just copied to another place to allow for using a different
one.
Andrew Wilkins (axwalk) wrote : | # |
Please take a look.
Andrew Wilkins (axwalk) wrote : | # |
On 2014/02/25 14:22:14, axw wrote:
> Please take a look.
This CL has jumped the shark, I guess, but I wanted to get it out there
to get feedback.
If the direction is good I will try to pare it back, keeping the
existing environs/cloudinit and related code, and remove all that in a
followup.
Andrew Wilkins (axwalk) wrote : | # |
This is *not* merged, lying bot! I created another branch and merged this in, removing all the bits I didn't care about. Bot merged the second branch and thought this one was merged too.
John A Meinel (jameinel) wrote : | # |
This revision is in the history, though maybe it didn't merge like it looks here?
Andrew Wilkins (axwalk) wrote : | # |
On 2014/02/25 14:27:20, axw wrote:
> On 2014/02/25 14:22:14, axw wrote:
> > Please take a look.
> This CL has jumped the shark, I guess, but I wanted to get it out
there to get
> feedback.
> If the direction is good I will try to pare it back, keeping the
existing
> environs/cloudinit and related code, and remove all that in a
followup.
This is superseded by https:/
Preview Diff
1 | === modified file 'agent/agent.go' |
2 | --- agent/agent.go 2014-02-18 05:43:06 +0000 |
3 | +++ agent/agent.go 2014-02-25 14:03:09 +0000 |
4 | @@ -30,7 +30,6 @@ |
5 | StorageAddr = "STORAGE_ADDR" |
6 | AgentServiceName = "AGENT_SERVICE_NAME" |
7 | MongoServiceName = "MONGO_SERVICE_NAME" |
8 | - RsyslogConfPath = "RSYSLOG_CONF_PATH" |
9 | BootstrapJobs = "BOOTSTRAP_JOBS" |
10 | ) |
11 | |
12 | |
13 | === modified file 'cmd/juju/environment_test.go' |
14 | --- cmd/juju/environment_test.go 2013-11-28 09:11:12 +0000 |
15 | +++ cmd/juju/environment_test.go 2014-02-25 14:03:09 +0000 |
16 | @@ -167,7 +167,6 @@ |
17 | "firewall-mode": "global", |
18 | "state-port": "1", |
19 | "api-port": "666", |
20 | - "syslog-port": "42", |
21 | } |
22 | |
23 | func (s *SetEnvironmentSuite) TestImmutableConfigValues(c *gc.C) { |
24 | |
25 | === modified file 'cmd/jujud/machine.go' |
26 | --- cmd/jujud/machine.go 2014-02-20 08:23:40 +0000 |
27 | +++ cmd/jujud/machine.go 2014-02-25 14:03:09 +0000 |
28 | @@ -18,7 +18,6 @@ |
29 | "launchpad.net/juju-core/cmd" |
30 | "launchpad.net/juju-core/container/kvm" |
31 | "launchpad.net/juju-core/instance" |
32 | - "launchpad.net/juju-core/log/syslog" |
33 | "launchpad.net/juju-core/names" |
34 | "launchpad.net/juju-core/provider" |
35 | "launchpad.net/juju-core/state" |
36 | @@ -42,6 +41,7 @@ |
37 | "launchpad.net/juju-core/worker/minunitsworker" |
38 | "launchpad.net/juju-core/worker/provisioner" |
39 | "launchpad.net/juju-core/worker/resumer" |
40 | + "launchpad.net/juju-core/worker/rsyslog" |
41 | "launchpad.net/juju-core/worker/terminationworker" |
42 | "launchpad.net/juju-core/worker/upgrader" |
43 | ) |
44 | @@ -65,6 +65,8 @@ |
45 | Conf AgentConf |
46 | MachineId string |
47 | runner worker.Runner |
48 | + |
49 | + rsyslogConfPath string |
50 | } |
51 | |
52 | // Info returns usage information for the command. |
53 | @@ -157,6 +159,8 @@ |
54 | return err |
55 | } |
56 | |
57 | +var newRsyslogConfigWorker = rsyslog.NewRsyslogConfigWorker |
58 | + |
59 | // APIWorker returns a Worker that connects to the API and starts any |
60 | // workers that need an API connection. |
61 | // |
62 | @@ -174,6 +178,14 @@ |
63 | break |
64 | } |
65 | } |
66 | + rsyslogMode := rsyslog.RsyslogModeForwarding |
67 | + for _, job := range entity.Jobs() { |
68 | + if job == params.JobManageEnviron { |
69 | + rsyslogMode = rsyslog.RsyslogModeAccumulate |
70 | + break |
71 | + } |
72 | + } |
73 | + |
74 | runner := newRunner(connectionIsFatal(st), moreImportant) |
75 | runner.StartWorker("machiner", func() (worker.Worker, error) { |
76 | return machiner.NewMachiner(st.Machiner(), agentConfig), nil |
77 | @@ -187,6 +199,9 @@ |
78 | runner.StartWorker("machineenvironmentworker", func() (worker.Worker, error) { |
79 | return machineenvironmentworker.NewMachineEnvironmentWorker(st.Environment(), agentConfig), nil |
80 | }) |
81 | + runner.StartWorker("rsyslog", func() (worker.Worker, error) { |
82 | + return newRsyslogConfigWorker(st.Rsyslog(), agentConfig, rsyslogMode) |
83 | + }) |
84 | |
85 | // If not a local provider bootstrap machine, start the worker to manage SSH keys. |
86 | providerType := agentConfig.Value(agent.ProviderType) |
87 | @@ -385,15 +400,6 @@ |
88 | errors = append(errors, fmt.Errorf("cannot remove service %q: %v", agentServiceName, err)) |
89 | } |
90 | } |
91 | - // Remove the rsyslog conf file and restart rsyslogd. |
92 | - if rsyslogConfPath := a.Conf.config.Value(agent.RsyslogConfPath); rsyslogConfPath != "" { |
93 | - if err := os.Remove(rsyslogConfPath); err != nil { |
94 | - errors = append(errors, err) |
95 | - } |
96 | - if err := syslog.Restart(); err != nil { |
97 | - errors = append(errors, err) |
98 | - } |
99 | - } |
100 | // Remove the juju-run symlink. |
101 | if err := os.Remove(jujuRun); err != nil && !os.IsNotExist(err) { |
102 | errors = append(errors, err) |
103 | |
104 | === modified file 'cmd/jujud/machine_test.go' |
105 | --- cmd/jujud/machine_test.go 2014-02-19 02:25:30 +0000 |
106 | +++ cmd/jujud/machine_test.go 2014-02-25 14:03:09 +0000 |
107 | @@ -28,6 +28,7 @@ |
108 | "launchpad.net/juju-core/state/api" |
109 | apideployer "launchpad.net/juju-core/state/api/deployer" |
110 | "launchpad.net/juju-core/state/api/params" |
111 | + apirsyslog "launchpad.net/juju-core/state/api/rsyslog" |
112 | charmtesting "launchpad.net/juju-core/state/apiserver/charmrevisionupdater/testing" |
113 | statetesting "launchpad.net/juju-core/state/testing" |
114 | "launchpad.net/juju-core/state/watcher" |
115 | @@ -40,10 +41,12 @@ |
116 | "launchpad.net/juju-core/utils/ssh" |
117 | sshtesting "launchpad.net/juju-core/utils/ssh/testing" |
118 | "launchpad.net/juju-core/version" |
119 | + "launchpad.net/juju-core/worker" |
120 | "launchpad.net/juju-core/worker/authenticationworker" |
121 | "launchpad.net/juju-core/worker/deployer" |
122 | "launchpad.net/juju-core/worker/instancepoller" |
123 | "launchpad.net/juju-core/worker/machineenvironmentworker" |
124 | + "launchpad.net/juju-core/worker/rsyslog" |
125 | "launchpad.net/juju-core/worker/upgrader" |
126 | ) |
127 | |
128 | @@ -750,6 +753,30 @@ |
129 | c.Assert(err, jc.Satisfies, os.IsNotExist) |
130 | } |
131 | |
132 | +func (s *MachineSuite) TestMachineAgentRsyslogManageEnviron(c *gc.C) { |
133 | + s.testMachineAgentRsyslogConfigWorker(c, state.JobManageEnviron, rsyslog.RsyslogModeAccumulate) |
134 | +} |
135 | + |
136 | +func (s *MachineSuite) TestMachineAgentRsyslogHostUnits(c *gc.C) { |
137 | + s.testMachineAgentRsyslogConfigWorker(c, state.JobHostUnits, rsyslog.RsyslogModeForwarding) |
138 | +} |
139 | + |
140 | +func (s *MachineSuite) testMachineAgentRsyslogConfigWorker(c *gc.C, job state.MachineJob, expectedMode rsyslog.RsyslogMode) { |
141 | + created := make(chan rsyslog.RsyslogMode, 1) |
142 | + s.PatchValue(&newRsyslogConfigWorker, func(_ *apirsyslog.State, _ agent.Config, mode rsyslog.RsyslogMode) (worker.Worker, error) { |
143 | + created <- mode |
144 | + return worker.NewRunner(isFatal, moreImportant), nil |
145 | + }) |
146 | + s.assertJobWithAPI(c, job, func(conf agent.Config, st *api.State) { |
147 | + select { |
148 | + case <-time.After(testing.LongWait): |
149 | + c.Fatalf("timeout while waiting for rsyslog worker to be created") |
150 | + case mode := <-created: |
151 | + c.Assert(mode, gc.Equals, expectedMode) |
152 | + } |
153 | + }) |
154 | +} |
155 | + |
156 | // MachineWithCharmsSuite provides infrastructure for tests which need to |
157 | // work with charms. |
158 | type MachineWithCharmsSuite struct { |
159 | |
160 | === modified file 'cmd/jujud/unit.go' |
161 | --- cmd/jujud/unit.go 2014-02-18 00:15:30 +0000 |
162 | +++ cmd/jujud/unit.go 2014-02-25 14:03:09 +0000 |
163 | @@ -15,6 +15,7 @@ |
164 | "launchpad.net/juju-core/state" |
165 | "launchpad.net/juju-core/worker" |
166 | workerlogger "launchpad.net/juju-core/worker/logger" |
167 | + "launchpad.net/juju-core/worker/rsyslog" |
168 | "launchpad.net/juju-core/worker/uniter" |
169 | "launchpad.net/juju-core/worker/upgrader" |
170 | ) |
171 | @@ -94,6 +95,9 @@ |
172 | runner.StartWorker("uniter", func() (worker.Worker, error) { |
173 | return uniter.NewUniter(st.Uniter(), entity.Tag(), dataDir), nil |
174 | }) |
175 | + runner.StartWorker("rsyslog", func() (worker.Worker, error) { |
176 | + return rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), agentConfig, rsyslog.RsyslogModeForwarding) |
177 | + }) |
178 | return newCloseWorker(runner, st), nil |
179 | } |
180 | |
181 | |
182 | === modified file 'container/testing/common.go' |
183 | --- container/testing/common.go 2013-12-04 04:33:23 +0000 |
184 | +++ container/testing/common.go 2014-02-25 14:03:09 +0000 |
185 | @@ -21,7 +21,6 @@ |
186 | stateInfo := jujutesting.FakeStateInfo(machineId) |
187 | apiInfo := jujutesting.FakeAPIInfo(machineId) |
188 | machineConfig := environs.NewMachineConfig(machineId, "fake-nonce", stateInfo, apiInfo) |
189 | - machineConfig.SyslogPort = 2345 |
190 | machineConfig.Tools = &tools.Tools{ |
191 | Version: version.MustParseBinary("2.3.4-foo-bar"), |
192 | URL: "http://tools.testing.invalid/2.3.4-foo-bar.tgz", |
193 | |
194 | === modified file 'environs/cloudinit.go' |
195 | --- environs/cloudinit.go 2014-02-13 05:22:01 +0000 |
196 | +++ environs/cloudinit.go 2014-02-25 14:03:09 +0000 |
197 | @@ -31,12 +31,6 @@ |
198 | // CloudInitOutputLog is the default cloud-init-output.log file path. |
199 | const CloudInitOutputLog = "/var/log/cloud-init-output.log" |
200 | |
201 | -// DefaultRsyslogConfPath is the default rsyslogd conf file path. |
202 | -const DefaultRsyslogConfPath = "/etc/rsyslog.d/25-juju.conf" |
203 | - |
204 | -// Override for testing. |
205 | -var RsyslogConfPath = DefaultRsyslogConfPath |
206 | - |
207 | // MongoServiceName is the default Upstart service name for Mongo. |
208 | const MongoServiceName = "juju-db" |
209 | |
210 | @@ -50,7 +44,6 @@ |
211 | DataDir: DataDir, |
212 | LogDir: LogDir, |
213 | CloudInitOutputLog: CloudInitOutputLog, |
214 | - RsyslogConfPath: RsyslogConfPath, |
215 | MachineAgentServiceName: "jujud-" + names.MachineTag(machineID), |
216 | MongoServiceName: MongoServiceName, |
217 | |
218 | @@ -85,7 +78,6 @@ |
219 | func PopulateMachineConfig(mcfg *cloudinit.MachineConfig, |
220 | providerType, authorizedKeys string, |
221 | sslHostnameVerification bool, |
222 | - syslogPort int, |
223 | proxy, aptProxy osenv.ProxySettings, |
224 | ) error { |
225 | if authorizedKeys == "" { |
226 | @@ -98,7 +90,6 @@ |
227 | mcfg.AgentEnvironment[agent.ProviderType] = providerType |
228 | mcfg.AgentEnvironment[agent.ContainerType] = string(mcfg.MachineContainerType) |
229 | mcfg.DisableSSLHostnameVerification = !sslHostnameVerification |
230 | - mcfg.SyslogPort = syslogPort |
231 | mcfg.ProxySettings = proxy |
232 | mcfg.AptProxySettings = aptProxy |
233 | return nil |
234 | @@ -122,7 +113,6 @@ |
235 | cfg.Type(), |
236 | cfg.AuthorizedKeys(), |
237 | cfg.SSLHostnameVerification(), |
238 | - cfg.SyslogPort(), |
239 | cfg.ProxySettings(), |
240 | cfg.AptProxySettings(), |
241 | ); err != nil { |
242 | |
243 | === modified file 'environs/cloudinit/cloudinit.go' |
244 | --- environs/cloudinit/cloudinit.go 2014-02-20 15:03:08 +0000 |
245 | +++ environs/cloudinit/cloudinit.go 2014-02-25 14:03:09 +0000 |
246 | @@ -20,7 +20,6 @@ |
247 | "launchpad.net/juju-core/environs/config" |
248 | "launchpad.net/juju-core/instance" |
249 | "launchpad.net/juju-core/juju/osenv" |
250 | - "launchpad.net/juju-core/log/syslog" |
251 | "launchpad.net/juju-core/names" |
252 | "launchpad.net/juju-core/state" |
253 | "launchpad.net/juju-core/state/api" |
254 | @@ -63,10 +62,6 @@ |
255 | // if StateServer is true. |
256 | APIPort int |
257 | |
258 | - // SyslogPort specifies the port number that will be used when |
259 | - // sending the log messages using rsyslog. |
260 | - SyslogPort int |
261 | - |
262 | // StateInfo holds the means for the new instance to communicate with the |
263 | // juju state. Unless the new machine is running a state server (StateServer is |
264 | // set), there must be at least one state server address supplied. |
265 | @@ -95,10 +90,6 @@ |
266 | // LogDir holds the directory that juju logs will be written to. |
267 | LogDir string |
268 | |
269 | - // RsyslogConfPath is the path to the rsyslogd conf file written |
270 | - // for configuring distributed logging. |
271 | - RsyslogConfPath string |
272 | - |
273 | // CloudInitOutputLog specifies the path to the output log for cloud-init. |
274 | // The directory containing the log file must already exist. |
275 | CloudInitOutputLog string |
276 | @@ -317,10 +308,6 @@ |
277 | fmt.Sprintf("printf %%s %s > $bin/downloaded-tools.txt", shquote(string(toolsJson))), |
278 | ) |
279 | |
280 | - if err := cfg.addLogging(c); err != nil { |
281 | - return err |
282 | - } |
283 | - |
284 | // We add the machine agent's configuration info |
285 | // before running bootstrap-state so that bootstrap-state |
286 | // has a chance to rerwrite it to change the password. |
287 | @@ -401,26 +388,6 @@ |
288 | return cfg.addMachineAgentToBoot(c, machineTag, cfg.MachineId) |
289 | } |
290 | |
291 | -func (cfg *MachineConfig) addLogging(c *cloudinit.Config) error { |
292 | - namespace := cfg.AgentEnvironment[agent.Namespace] |
293 | - var configRenderer *syslog.SyslogConfig |
294 | - if cfg.StateServer { |
295 | - configRenderer = syslog.NewAccumulateConfig( |
296 | - names.MachineTag(cfg.MachineId), cfg.SyslogPort, namespace) |
297 | - } else { |
298 | - configRenderer = syslog.NewForwardConfig( |
299 | - names.MachineTag(cfg.MachineId), cfg.SyslogPort, namespace, cfg.stateHostAddrs()) |
300 | - } |
301 | - configRenderer.LogDir = cfg.LogDir |
302 | - content, err := configRenderer.Render() |
303 | - if err != nil { |
304 | - return err |
305 | - } |
306 | - c.AddFile(cfg.RsyslogConfPath, string(content), 0644) |
307 | - c.AddRunCmd("restart rsyslog") |
308 | - return nil |
309 | -} |
310 | - |
311 | func (cfg *MachineConfig) dataFile(name string) string { |
312 | return path.Join(cfg.DataDir, name) |
313 | } |
314 | @@ -464,7 +431,6 @@ |
315 | if err != nil { |
316 | return nil, err |
317 | } |
318 | - acfg.SetValue(agent.RsyslogConfPath, cfg.RsyslogConfPath) |
319 | acfg.SetValue(agent.AgentServiceName, cfg.MachineAgentServiceName) |
320 | if cfg.StateServer { |
321 | acfg.SetValue(agent.MongoServiceName, cfg.MongoServiceName) |
322 | @@ -656,9 +622,6 @@ |
323 | if cfg.CloudInitOutputLog == "" { |
324 | return fmt.Errorf("missing cloud-init output log path") |
325 | } |
326 | - if cfg.RsyslogConfPath == "" { |
327 | - return fmt.Errorf("missing rsyslog.d conf path") |
328 | - } |
329 | if cfg.Tools == nil { |
330 | return fmt.Errorf("missing tools") |
331 | } |
332 | @@ -674,9 +637,6 @@ |
333 | if cfg.APIInfo == nil { |
334 | return fmt.Errorf("missing API info") |
335 | } |
336 | - if cfg.SyslogPort == 0 { |
337 | - return fmt.Errorf("missing syslog port") |
338 | - } |
339 | if len(cfg.APIInfo.CACert) == 0 { |
340 | return fmt.Errorf("missing API CA certificate") |
341 | } |
342 | |
343 | === modified file 'environs/cloudinit/cloudinit_test.go' |
344 | --- environs/cloudinit/cloudinit_test.go 2014-02-21 17:32:31 +0000 |
345 | +++ environs/cloudinit/cloudinit_test.go 2014-02-25 14:03:09 +0000 |
346 | @@ -76,7 +76,6 @@ |
347 | StateServerKey: serverKey, |
348 | StatePort: 37017, |
349 | APIPort: 17070, |
350 | - SyslogPort: 514, |
351 | MachineNonce: "FAKE_NONCE", |
352 | StateInfo: &state.Info{ |
353 | Password: "arble", |
354 | @@ -90,7 +89,6 @@ |
355 | DataDir: environs.DataDir, |
356 | LogDir: environs.LogDir, |
357 | CloudInitOutputLog: environs.CloudInitOutputLog, |
358 | - RsyslogConfPath: environs.RsyslogConfPath, |
359 | StateInfoURL: "some-url", |
360 | SystemPrivateSSHKey: "private rsa key", |
361 | MachineAgentServiceName: "jujud-machine-0", |
362 | @@ -116,9 +114,6 @@ |
363 | tar zxf \$bin/tools.tar.gz -C \$bin |
364 | rm \$bin/tools\.tar\.gz && rm \$bin/juju1\.2\.3-precise-amd64\.sha256 |
365 | printf %s '{"version":"1\.2\.3-precise-amd64","url":"http://foo\.com/tools/releases/juju1\.2\.3-precise-amd64\.tgz","sha256":"1234","size":10}' > \$bin/downloaded-tools\.txt |
366 | -install -D -m 644 /dev/null '/etc/rsyslog\.d/25-juju\.conf' |
367 | -printf '%s\\n' '.*' > '/etc/rsyslog.d/25-juju.conf' |
368 | -restart rsyslog |
369 | mkdir -p '/var/lib/juju/agents/machine-0' |
370 | install -m 644 /dev/null '/var/lib/juju/agents/machine-0/format' |
371 | printf '%s\\n' '.*' > '/var/lib/juju/agents/machine-0/format' |
372 | @@ -165,7 +160,6 @@ |
373 | StateServerKey: serverKey, |
374 | StatePort: 37017, |
375 | APIPort: 17070, |
376 | - SyslogPort: 514, |
377 | MachineNonce: "FAKE_NONCE", |
378 | StateInfo: &state.Info{ |
379 | Password: "arble", |
380 | @@ -179,7 +173,6 @@ |
381 | DataDir: environs.DataDir, |
382 | LogDir: environs.LogDir, |
383 | CloudInitOutputLog: environs.CloudInitOutputLog, |
384 | - RsyslogConfPath: environs.RsyslogConfPath, |
385 | StateInfoURL: "some-url", |
386 | SystemPrivateSSHKey: "private rsa key", |
387 | MachineAgentServiceName: "jujud-machine-0", |
388 | @@ -207,7 +200,6 @@ |
389 | DataDir: environs.DataDir, |
390 | LogDir: environs.LogDir, |
391 | CloudInitOutputLog: environs.CloudInitOutputLog, |
392 | - RsyslogConfPath: environs.RsyslogConfPath, |
393 | StateServer: false, |
394 | Tools: newSimpleTools("1.2.3-linux-amd64"), |
395 | MachineNonce: "FAKE_NONCE", |
396 | @@ -223,7 +215,6 @@ |
397 | Password: "bletch", |
398 | CACert: []byte("CA CERT\n" + testing.CACert), |
399 | }, |
400 | - SyslogPort: 514, |
401 | MachineAgentServiceName: "jujud-machine-99", |
402 | }, |
403 | expectScripts: ` |
404 | @@ -244,9 +235,6 @@ |
405 | tar zxf \$bin/tools.tar.gz -C \$bin |
406 | rm \$bin/tools\.tar\.gz && rm \$bin/juju1\.2\.3-linux-amd64\.sha256 |
407 | printf %s '{"version":"1\.2\.3-linux-amd64","url":"http://foo\.com/tools/releases/juju1\.2\.3-linux-amd64\.tgz","sha256":"1234","size":10}' > \$bin/downloaded-tools\.txt |
408 | -install -D -m 644 /dev/null '/etc/rsyslog\.d/25-juju\.conf' |
409 | -printf '%s\\n' '.*' > '/etc/rsyslog\.d/25-juju\.conf' |
410 | -restart rsyslog |
411 | mkdir -p '/var/lib/juju/agents/machine-99' |
412 | install -m 644 /dev/null '/var/lib/juju/agents/machine-99/format' |
413 | printf '%s\\n' '.*' > '/var/lib/juju/agents/machine-99/format' |
414 | @@ -267,7 +255,6 @@ |
415 | DataDir: environs.DataDir, |
416 | LogDir: environs.LogDir, |
417 | CloudInitOutputLog: environs.CloudInitOutputLog, |
418 | - RsyslogConfPath: environs.RsyslogConfPath, |
419 | StateServer: false, |
420 | Tools: newSimpleTools("1.2.3-linux-amd64"), |
421 | MachineNonce: "FAKE_NONCE", |
422 | @@ -283,13 +270,10 @@ |
423 | Password: "bletch", |
424 | CACert: []byte("CA CERT\n" + testing.CACert), |
425 | }, |
426 | - SyslogPort: 514, |
427 | MachineAgentServiceName: "jujud-machine-2-lxc-1", |
428 | }, |
429 | inexactMatch: true, |
430 | expectScripts: ` |
431 | -printf '%s\\n' '.*' > '/etc/rsyslog\.d/25-juju\.conf' |
432 | -restart rsyslog |
433 | mkdir -p '/var/lib/juju/agents/machine-2-lxc-1' |
434 | install -m 644 /dev/null '/var/lib/juju/agents/machine-2-lxc-1/format' |
435 | printf '%s\\n' '.*' > '/var/lib/juju/agents/machine-2-lxc-1/format' |
436 | @@ -308,7 +292,6 @@ |
437 | DataDir: environs.DataDir, |
438 | LogDir: environs.LogDir, |
439 | CloudInitOutputLog: environs.CloudInitOutputLog, |
440 | - RsyslogConfPath: environs.RsyslogConfPath, |
441 | StateServer: false, |
442 | Tools: newSimpleTools("1.2.3-linux-amd64"), |
443 | MachineNonce: "FAKE_NONCE", |
444 | @@ -324,7 +307,6 @@ |
445 | Password: "bletch", |
446 | CACert: []byte("CA CERT\n" + testing.CACert), |
447 | }, |
448 | - SyslogPort: 514, |
449 | DisableSSLHostnameVerification: true, |
450 | MachineAgentServiceName: "jujud-machine-99", |
451 | }, |
452 | @@ -345,7 +327,6 @@ |
453 | StateServerKey: serverKey, |
454 | StatePort: 37017, |
455 | APIPort: 17070, |
456 | - SyslogPort: 514, |
457 | MachineNonce: "FAKE_NONCE", |
458 | StateInfo: &state.Info{ |
459 | Password: "arble", |
460 | @@ -358,7 +339,6 @@ |
461 | DataDir: environs.DataDir, |
462 | LogDir: environs.LogDir, |
463 | CloudInitOutputLog: environs.CloudInitOutputLog, |
464 | - RsyslogConfPath: environs.RsyslogConfPath, |
465 | StateInfoURL: "some-url", |
466 | SystemPrivateSSHKey: "private rsa key", |
467 | MachineAgentServiceName: "jujud-machine-0", |
468 | @@ -644,9 +624,6 @@ |
469 | {"missing API info", func(cfg *cloudinit.MachineConfig) { |
470 | cfg.APIInfo = nil |
471 | }}, |
472 | - {"missing syslog port", func(cfg *cloudinit.MachineConfig) { |
473 | - cfg.SyslogPort = 0 |
474 | - }}, |
475 | {"missing state hosts", func(cfg *cloudinit.MachineConfig) { |
476 | cfg.StateServer = false |
477 | cfg.StateInfo = &state.Info{ |
478 | @@ -696,9 +673,6 @@ |
479 | {"missing cloud-init output log path", func(cfg *cloudinit.MachineConfig) { |
480 | cfg.CloudInitOutputLog = "" |
481 | }}, |
482 | - {"missing rsyslog.d conf path", func(cfg *cloudinit.MachineConfig) { |
483 | - cfg.RsyslogConfPath = "" |
484 | - }}, |
485 | {"missing tools", func(cfg *cloudinit.MachineConfig) { |
486 | cfg.Tools = nil |
487 | }}, |
488 | @@ -765,7 +739,6 @@ |
489 | StateServerKey: serverKey, |
490 | StatePort: 1234, |
491 | APIPort: 1235, |
492 | - SyslogPort: 2345, |
493 | MachineId: "99", |
494 | Tools: newSimpleTools("9.9.9-linux-arble"), |
495 | AuthorizedKeys: "sshkey1", |
496 | @@ -783,7 +756,6 @@ |
497 | DataDir: environs.DataDir, |
498 | LogDir: environs.LogDir, |
499 | CloudInitOutputLog: environs.CloudInitOutputLog, |
500 | - RsyslogConfPath: environs.RsyslogConfPath, |
501 | MachineNonce: "FAKE_NONCE", |
502 | SystemPrivateSSHKey: "private rsa key", |
503 | MachineAgentServiceName: "jujud-machine-99", |
504 | @@ -803,12 +775,20 @@ |
505 | } |
506 | } |
507 | |
508 | -func (*cloudinitSuite) createMachineConfig(c *gc.C, environConfig *config.Config) *cloudinit.MachineConfig { |
509 | +func (*cloudinitSuite) createMachineConfig(c *gc.C, environConfig *config.Config, stateServer bool) *cloudinit.MachineConfig { |
510 | machineId := "42" |
511 | machineNonce := "fake-nonce" |
512 | stateInfo := jujutesting.FakeStateInfo(machineId) |
513 | apiInfo := jujutesting.FakeAPIInfo(machineId) |
514 | - machineConfig := environs.NewMachineConfig(machineId, machineNonce, stateInfo, apiInfo) |
515 | + var machineConfig *cloudinit.MachineConfig |
516 | + if stateServer { |
517 | + var err error |
518 | + environConfig, err = environConfig.Apply(map[string]interface{}{"agent-version": "2.3.4"}) |
519 | + c.Assert(err, gc.IsNil) |
520 | + machineConfig = environs.NewBootstrapMachineConfig("http://testing.invalid/provider-state", "invalid ssh key") |
521 | + } else { |
522 | + machineConfig = environs.NewMachineConfig(machineId, machineNonce, stateInfo, apiInfo) |
523 | + } |
524 | machineConfig.Tools = &tools.Tools{ |
525 | Version: version.MustParseBinary("2.3.4-foo-bar"), |
526 | URL: "http://tools.testing.invalid/2.3.4-foo-bar.tgz", |
527 | @@ -820,7 +800,7 @@ |
528 | |
529 | func (s *cloudinitSuite) TestAptProxyNotWrittenIfNotSet(c *gc.C) { |
530 | environConfig := minimalConfig(c) |
531 | - machineCfg := s.createMachineConfig(c, environConfig) |
532 | + machineCfg := s.createMachineConfig(c, environConfig, false) |
533 | cloudcfg := coreCloudinit.New() |
534 | err := cloudinit.Configure(machineCfg, cloudcfg) |
535 | c.Assert(err, gc.IsNil) |
536 | @@ -835,7 +815,7 @@ |
537 | "apt-http-proxy": "http://user@10.0.0.1", |
538 | }) |
539 | c.Assert(err, gc.IsNil) |
540 | - machineCfg := s.createMachineConfig(c, environConfig) |
541 | + machineCfg := s.createMachineConfig(c, environConfig, false) |
542 | cloudcfg := coreCloudinit.New() |
543 | err = cloudinit.Configure(machineCfg, cloudcfg) |
544 | c.Assert(err, gc.IsNil) |
545 | @@ -851,7 +831,7 @@ |
546 | "http-proxy": "http://user@10.0.0.1", |
547 | }) |
548 | c.Assert(err, gc.IsNil) |
549 | - machineCfg := s.createMachineConfig(c, environConfig) |
550 | + machineCfg := s.createMachineConfig(c, environConfig, false) |
551 | cloudcfg := coreCloudinit.New() |
552 | err = cloudinit.Configure(machineCfg, cloudcfg) |
553 | c.Assert(err, gc.IsNil) |
554 | |
555 | === modified file 'environs/cloudinit_test.go' |
556 | --- environs/cloudinit_test.go 2014-01-23 05:45:58 +0000 |
557 | +++ environs/cloudinit_test.go 2014-02-25 14:03:09 +0000 |
558 | @@ -63,7 +63,6 @@ |
559 | StateInfo: &state.Info{Tag: "not touched"}, |
560 | APIInfo: &api.Info{Tag: "not touched"}, |
561 | DisableSSLHostnameVerification: false, |
562 | - SyslogPort: 2345, |
563 | }) |
564 | } |
565 | |
566 | @@ -71,7 +70,6 @@ |
567 | attrs := dummySampleConfig().Merge(testing.Attrs{ |
568 | "authorized-keys": "we-are-the-keys", |
569 | "ssl-hostname-verification": false, |
570 | - "syslog-port": 8888, |
571 | }) |
572 | cfg, err := config.New(config.NoDefaults, attrs) |
573 | c.Assert(err, gc.IsNil) |
574 | @@ -90,7 +88,6 @@ |
575 | StateInfo: &state.Info{Tag: "not touched"}, |
576 | APIInfo: &api.Info{Tag: "not touched"}, |
577 | DisableSSLHostnameVerification: true, |
578 | - SyslogPort: 8888, |
579 | }) |
580 | } |
581 | |
582 | @@ -178,11 +175,9 @@ |
583 | DataDir: environs.DataDir, |
584 | LogDir: environs.LogDir, |
585 | CloudInitOutputLog: environs.CloudInitOutputLog, |
586 | - RsyslogConfPath: environs.RsyslogConfPath, |
587 | Config: envConfig, |
588 | StatePort: envConfig.StatePort(), |
589 | APIPort: envConfig.APIPort(), |
590 | - SyslogPort: envConfig.SyslogPort(), |
591 | StateServer: stateServer, |
592 | AgentEnvironment: map[string]string{agent.ProviderType: "dummy"}, |
593 | AuthorizedKeys: "wheredidileavemykeys", |
594 | |
595 | === modified file 'environs/config/config.go' |
596 | --- environs/config/config.go 2014-02-12 04:54:19 +0000 |
597 | +++ environs/config/config.go 2014-02-25 14:03:09 +0000 |
598 | @@ -43,9 +43,9 @@ |
599 | // DefaultApiPort is the default port the API server is listening on. |
600 | DefaultAPIPort int = 17070 |
601 | |
602 | - // DefaultSyslogPort is the default port that the syslog UDP listener is |
603 | + // DefaultSyslogPort is the default port that the syslog UDP/TCP listener is |
604 | // listening on. |
605 | - DefaultSyslogPort int = 514 |
606 | + DefaultSyslogPort int = 6514 |
607 | |
608 | // DefaultBootstrapSSHTimeout is the amount of time to wait |
609 | // contacting a state server, in seconds. |
610 | @@ -427,6 +427,16 @@ |
611 | return c.mustInt("syslog-port") |
612 | } |
613 | |
614 | +// RsyslogCACert returns the certificate of the CA that signed the |
615 | +// rsyslog certificate, in PEM format, or nil if one hasn't been |
616 | +// generated yet. |
617 | +func (c *Config) RsyslogCACert() []byte { |
618 | + if s, ok := c.defined["rsyslog-ca-cert"]; ok { |
619 | + return []byte(s.(string)) |
620 | + } |
621 | + return nil |
622 | +} |
623 | + |
624 | // AuthorizedKeys returns the content for ssh's authorized_keys file. |
625 | func (c *Config) AuthorizedKeys() string { |
626 | return c.mustString("authorized-keys") |
627 | @@ -668,6 +678,7 @@ |
628 | "state-port": schema.ForceInt(), |
629 | "api-port": schema.ForceInt(), |
630 | "syslog-port": schema.ForceInt(), |
631 | + "rsyslog-ca-cert": schema.String(), |
632 | "logging-config": schema.String(), |
633 | "charm-store-auth": schema.String(), |
634 | "provisioner-safe-mode": schema.Bool(), |
635 | @@ -711,6 +722,7 @@ |
636 | "bootstrap-timeout": schema.Omit, |
637 | "bootstrap-retry-delay": schema.Omit, |
638 | "bootstrap-addresses-delay": schema.Omit, |
639 | + "rsyslog-ca-cert": schema.Omit, |
640 | |
641 | // Deprecated fields, retain for backwards compatibility. |
642 | "tools-url": "", |
643 | @@ -742,6 +754,9 @@ |
644 | |
645 | var defaults = allDefaults() |
646 | |
647 | +// allDefaults returns a schema.Defaults that contains |
648 | +// defaults to be used when creating a new config with |
649 | +// UseDefaults. |
650 | func allDefaults() schema.Defaults { |
651 | d := schema.Defaults{ |
652 | "default-series": DefaultSeries, |
653 | @@ -756,7 +771,9 @@ |
654 | "bootstrap-addresses-delay": DefaultBootstrapSSHAddressesDelay, |
655 | } |
656 | for attr, val := range alwaysOptional { |
657 | - d[attr] = val |
658 | + if _, ok := d[attr]; !ok { |
659 | + d[attr] = val |
660 | + } |
661 | } |
662 | return d |
663 | } |
664 | @@ -786,7 +803,6 @@ |
665 | "firewall-mode", |
666 | "state-port", |
667 | "api-port", |
668 | - "syslog-port", |
669 | "bootstrap-timeout", |
670 | "bootstrap-retry-delay", |
671 | "bootstrap-addresses-delay", |
672 | |
673 | === modified file 'environs/config/config_test.go' |
674 | --- environs/config/config_test.go 2014-02-12 04:54:19 +0000 |
675 | +++ environs/config/config_test.go 2014-02-25 14:03:09 +0000 |
676 | @@ -1072,11 +1072,6 @@ |
677 | new: testing.Attrs{"api-port": 42}, |
678 | err: `cannot change api-port from 17070 to 42`, |
679 | }, { |
680 | - about: "Cannot change the syslog-port", |
681 | - old: testing.Attrs{"syslog-port": 345}, |
682 | - new: testing.Attrs{"syslog-port": 42}, |
683 | - err: `cannot change syslog-port from 345 to 42`, |
684 | -}, { |
685 | about: "Can change the state-port from explicit-default to implicit-default", |
686 | old: testing.Attrs{"state-port": config.DefaultStatePort}, |
687 | }, { |
688 | @@ -1096,10 +1091,6 @@ |
689 | about: "Cannot change the api-port from implicit-default to different value", |
690 | new: testing.Attrs{"api-port": 42}, |
691 | err: `cannot change api-port from 17070 to 42`, |
692 | -}, { |
693 | - about: "Cannot change the syslog-port from implicit-default to different value", |
694 | - new: testing.Attrs{"syslog-port": 42}, |
695 | - err: `cannot change syslog-port from 514 to 42`, |
696 | }} |
697 | |
698 | func (*ConfigSuite) TestValidateChange(c *gc.C) { |
699 | |
700 | === modified file 'log/syslog/config.go' |
701 | --- log/syslog/config.go 2014-01-30 22:12:42 +0000 |
702 | +++ log/syslog/config.go 2014-02-25 14:03:09 +0000 |
703 | @@ -35,7 +35,7 @@ |
704 | // |
705 | // if $syslogtag startswith "juju{{namespace}}-" then |
706 | // action(type="omfile" |
707 | -// File="/var/log/juju{{namespace}}/all-machines.log" |
708 | +// File="{{logDir}}/all-machines.log" |
709 | // Template="JujuLogFormat{{namespace}}" |
710 | // FileCreateMode="0644") |
711 | // & stop |
712 | @@ -52,15 +52,21 @@ |
713 | $InputFileStateFile {{logfileName}}{{namespace}} |
714 | $InputRunFileMonitor |
715 | |
716 | -$ModLoad imudp |
717 | -$UDPServerRun {{portNumber}} |
718 | +$ModLoad imtcp |
719 | +$DefaultNetstreamDriver gtls |
720 | +$DefaultNetstreamDriverCAFile {{tlsCACertPath}} |
721 | +$DefaultNetstreamDriverCertFile {{tlsCertPath}} |
722 | +$DefaultNetstreamDriverKeyFile {{tlsKeyPath}} |
723 | +$InputTCPServerStreamDriverAuthMode anon |
724 | +$InputTCPServerStreamDriverMode 1 # run driver in TLS-only mode |
725 | +$InputTCPServerRun {{portNumber}} |
726 | |
727 | # Messages received from remote rsyslog machines have messages prefixed with a space, |
728 | # so add one in for local messages too if needed. |
729 | $template JujuLogFormat{{namespace}},"%syslogtag:{{tagStart}}:$%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" |
730 | |
731 | $FileCreateMode 0644 |
732 | -:syslogtag, startswith, "juju{{namespace}}-" /var/log/juju{{namespace}}/all-machines.log;JujuLogFormat{{namespace}} |
733 | +:syslogtag, startswith, "juju{{namespace}}-" {{logDir}}/all-machines.log;JujuLogFormat{{namespace}} |
734 | & ~ |
735 | $FileCreateMode 0640 |
736 | ` |
737 | @@ -70,6 +76,12 @@ |
738 | const nodeRsyslogTemplate = ` |
739 | $ModLoad imfile |
740 | |
741 | +# Enable reliable forwarding. |
742 | +$ActionQueueType LinkedList |
743 | +$ActionQueueFileName {{logfileName}}{{namespace}} |
744 | +$ActionResumeRetryCount -1 |
745 | +$ActionQueueSaveOnShutdown on |
746 | + |
747 | $InputFilePersistStateInterval 50 |
748 | $InputFilePollInterval 5 |
749 | $InputFileName {{logfilePath}} |
750 | @@ -77,12 +89,22 @@ |
751 | $InputFileStateFile {{logfileName}}{{namespace}} |
752 | $InputRunFileMonitor |
753 | |
754 | +$DefaultNetstreamDriver gtls |
755 | +$DefaultNetstreamDriverCAFile {{tlsCACertPath}} |
756 | +$ActionSendStreamDriverAuthMode anon |
757 | +$ActionSendStreamDriverMode 1 # run driver in TLS-only mode |
758 | + |
759 | $template LongTagForwardFormat,"<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg%" |
760 | |
761 | -:syslogtag, startswith, "juju{{namespace}}-" @{{bootstrapIP}}:{{portNumber}};LongTagForwardFormat |
762 | +:syslogtag, startswith, "juju{{namespace}}-" @@{{bootstrapIP}}:{{portNumber}};LongTagForwardFormat |
763 | & ~ |
764 | ` |
765 | |
766 | +// nodeRsyslogTemplateTLSHeader is prepended to |
767 | +// nodeRsyslogTemplate if TLS is to be used. |
768 | +const nodeRsyslogTemplateTLSHeader = ` |
769 | +` |
770 | + |
771 | const defaultConfigDir = "/etc/rsyslog.d" |
772 | |
773 | // SyslogConfigRenderer instances are used to generate a rsyslog conf file. |
774 | @@ -104,7 +126,15 @@ |
775 | LogFileName string |
776 | // the addresses of the state server to which messages should be forwarded. |
777 | StateServerAddresses []string |
778 | - // the port number for the udp listener |
779 | + // TLSCACertPath is the full path to the CA certificate that |
780 | + // signed the rsyslog server's certificate. If this is non-empty, |
781 | + // then TLS will be used. |
782 | + TLSCACertPath string |
783 | + // TLSCertPath is the full path to the server's certificate. |
784 | + TLSCertPath string |
785 | + // TLSKeyPath is the full path to the server's private key. |
786 | + TLSKeyPath string |
787 | + // the port number for the listener |
788 | Port int |
789 | // the directory for the logfiles |
790 | LogDir string |
791 | @@ -153,7 +183,6 @@ |
792 | |
793 | // Render generates the rsyslog config. |
794 | func (slConfig *SyslogConfig) Render() ([]byte, error) { |
795 | - |
796 | // TODO: for HA, we will want to send to all state server addresses (maybe). |
797 | var bootstrapIP = func() string { |
798 | addr := slConfig.StateServerAddresses[0] |
799 | @@ -167,13 +196,16 @@ |
800 | |
801 | t := template.New("") |
802 | t.Funcs(template.FuncMap{ |
803 | - "logfileName": func() string { return slConfig.LogFileName }, |
804 | - "bootstrapIP": bootstrapIP, |
805 | - "logfilePath": logFilePath, |
806 | - "portNumber": func() int { return slConfig.Port }, |
807 | - "logDir": func() string { return slConfig.LogDir }, |
808 | - "namespace": func() string { return slConfig.Namespace }, |
809 | - "tagStart": func() int { return tagOffset + len(slConfig.Namespace) }, |
810 | + "logfileName": func() string { return slConfig.LogFileName }, |
811 | + "bootstrapIP": bootstrapIP, |
812 | + "logfilePath": logFilePath, |
813 | + "portNumber": func() int { return slConfig.Port }, |
814 | + "logDir": func() string { return slConfig.LogDir }, |
815 | + "namespace": func() string { return slConfig.Namespace }, |
816 | + "tagStart": func() int { return tagOffset + len(slConfig.Namespace) }, |
817 | + "tlsCACertPath": func() string { return slConfig.TLSCACertPath }, |
818 | + "tlsCertPath": func() string { return slConfig.TLSCertPath }, |
819 | + "tlsKeyPath": func() string { return slConfig.TLSKeyPath }, |
820 | }) |
821 | |
822 | // Process the rsyslog config template and echo to the conf file. |
823 | |
824 | === modified file 'log/syslog/config_test.go' |
825 | --- log/syslog/config_test.go 2014-02-13 05:22:01 +0000 |
826 | +++ log/syslog/config_test.go 2014-02-25 14:03:09 +0000 |
827 | @@ -43,12 +43,18 @@ |
828 | |
829 | func (s *SyslogConfigSuite) TestAccumulateConfigRender(c *gc.C) { |
830 | syslogConfigRenderer := syslog.NewAccumulateConfig("some-machine", 8888, "") |
831 | + syslogConfigRenderer.TLSCACertPath = "/var/log/juju/ca.pem" |
832 | + syslogConfigRenderer.TLSCertPath = "/var/log/juju/cert.pem" |
833 | + syslogConfigRenderer.TLSKeyPath = "/var/log/juju/key.pem" |
834 | s.assertRsyslogConfigContents( |
835 | c, syslogConfigRenderer, syslogtesting.ExpectedAccumulateSyslogConf(c, "some-machine", "", 8888)) |
836 | } |
837 | |
838 | func (s *SyslogConfigSuite) TestAccumulateConfigWrite(c *gc.C) { |
839 | syslogConfigRenderer := syslog.NewAccumulateConfig("some-machine", 8888, "") |
840 | + syslogConfigRenderer.TLSCACertPath = "/var/log/juju/ca.pem" |
841 | + syslogConfigRenderer.TLSCertPath = "/var/log/juju/cert.pem" |
842 | + syslogConfigRenderer.TLSKeyPath = "/var/log/juju/key.pem" |
843 | syslogConfigRenderer.ConfigDir = s.configDir |
844 | syslogConfigRenderer.ConfigFileName = "rsyslog.conf" |
845 | s.assertRsyslogConfigPath(c, syslogConfigRenderer) |
846 | @@ -61,24 +67,30 @@ |
847 | |
848 | func (s *SyslogConfigSuite) TestAccumulateConfigRenderWithNamespace(c *gc.C) { |
849 | syslogConfigRenderer := syslog.NewAccumulateConfig("some-machine", 8888, "namespace") |
850 | + syslogConfigRenderer.TLSCACertPath = "/var/log/juju/ca.pem" |
851 | + syslogConfigRenderer.TLSCertPath = "/var/log/juju/cert.pem" |
852 | + syslogConfigRenderer.TLSKeyPath = "/var/log/juju/key.pem" |
853 | s.assertRsyslogConfigContents( |
854 | c, syslogConfigRenderer, syslogtesting.ExpectedAccumulateSyslogConf(c, "some-machine", "namespace", 8888)) |
855 | } |
856 | |
857 | func (s *SyslogConfigSuite) TestForwardConfigRender(c *gc.C) { |
858 | syslogConfigRenderer := syslog.NewForwardConfig("some-machine", 999, "", []string{"server"}) |
859 | + syslogConfigRenderer.TLSCACertPath = "/var/log/juju/ca.pem" |
860 | s.assertRsyslogConfigContents( |
861 | c, syslogConfigRenderer, syslogtesting.ExpectedForwardSyslogConf(c, "some-machine", "", 999)) |
862 | } |
863 | |
864 | func (s *SyslogConfigSuite) TestForwardConfigRenderWithNamespace(c *gc.C) { |
865 | syslogConfigRenderer := syslog.NewForwardConfig("some-machine", 999, "namespace", []string{"server"}) |
866 | + syslogConfigRenderer.TLSCACertPath = "/var/log/juju/ca.pem" |
867 | s.assertRsyslogConfigContents( |
868 | c, syslogConfigRenderer, syslogtesting.ExpectedForwardSyslogConf(c, "some-machine", "namespace", 999)) |
869 | } |
870 | |
871 | func (s *SyslogConfigSuite) TestForwardConfigWrite(c *gc.C) { |
872 | syslogConfigRenderer := syslog.NewForwardConfig("some-machine", 999, "", []string{"server"}) |
873 | + syslogConfigRenderer.TLSCACertPath = "/var/log/juju/ca.pem" |
874 | syslogConfigRenderer.ConfigDir = s.configDir |
875 | syslogConfigRenderer.ConfigFileName = "rsyslog.conf" |
876 | s.assertRsyslogConfigPath(c, syslogConfigRenderer) |
877 | |
878 | === modified file 'log/syslog/testing/syslogconf.go' |
879 | --- log/syslog/testing/syslogconf.go 2014-02-13 05:41:33 +0000 |
880 | +++ log/syslog/testing/syslogconf.go 2014-02-25 14:03:09 +0000 |
881 | @@ -20,15 +20,21 @@ |
882 | $InputFileStateFile {{machine}}{{namespace}} |
883 | $InputRunFileMonitor |
884 | |
885 | -$ModLoad imudp |
886 | -$UDPServerRun {{port}} |
887 | +$ModLoad imtcp |
888 | +$DefaultNetstreamDriver gtls |
889 | +$DefaultNetstreamDriverCAFile /var/log/juju/ca.pem |
890 | +$DefaultNetstreamDriverCertFile /var/log/juju/cert.pem |
891 | +$DefaultNetstreamDriverKeyFile /var/log/juju/key.pem |
892 | +$InputTCPServerStreamDriverAuthMode anon |
893 | +$InputTCPServerStreamDriverMode 1 # run driver in TLS-only mode |
894 | +$InputTCPServerRun {{port}} |
895 | |
896 | # Messages received from remote rsyslog machines have messages prefixed with a space, |
897 | # so add one in for local messages too if needed. |
898 | $template JujuLogFormat{{namespace}},"%syslogtag:{{offset}}:$%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" |
899 | |
900 | $FileCreateMode 0644 |
901 | -:syslogtag, startswith, "juju{{namespace}}-" /var/log/juju{{namespace}}/all-machines.log;JujuLogFormat{{namespace}} |
902 | +:syslogtag, startswith, "juju{{namespace}}-" /var/log/juju/all-machines.log;JujuLogFormat{{namespace}} |
903 | & ~ |
904 | $FileCreateMode 0640 |
905 | ` |
906 | @@ -55,6 +61,12 @@ |
907 | var expectedForwardSyslogConfTemplate = ` |
908 | $ModLoad imfile |
909 | |
910 | +# Enable reliable forwarding. |
911 | +$ActionQueueType LinkedList |
912 | +$ActionQueueFileName {{machine}}{{namespace}} |
913 | +$ActionResumeRetryCount -1 |
914 | +$ActionQueueSaveOnShutdown on |
915 | + |
916 | $InputFilePersistStateInterval 50 |
917 | $InputFilePollInterval 5 |
918 | $InputFileName /var/log/juju/{{machine}}.log |
919 | @@ -62,9 +74,14 @@ |
920 | $InputFileStateFile {{machine}}{{namespace}} |
921 | $InputRunFileMonitor |
922 | |
923 | +$DefaultNetstreamDriver gtls |
924 | +$DefaultNetstreamDriverCAFile /var/log/juju/ca.pem |
925 | +$ActionSendStreamDriverAuthMode anon |
926 | +$ActionSendStreamDriverMode 1 # run driver in TLS-only mode |
927 | + |
928 | $template LongTagForwardFormat,"<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg%" |
929 | |
930 | -:syslogtag, startswith, "juju{{namespace}}-" @server:{{port}};LongTagForwardFormat |
931 | +:syslogtag, startswith, "juju{{namespace}}-" @@server:{{port}};LongTagForwardFormat |
932 | & ~ |
933 | ` |
934 | |
935 | |
936 | === modified file 'provider/azure/customdata_test.go' |
937 | --- provider/azure/customdata_test.go 2014-01-23 05:21:21 +0000 |
938 | +++ provider/azure/customdata_test.go 2014-02-25 14:03:09 +0000 |
939 | @@ -33,7 +33,6 @@ |
940 | DataDir: environs.DataDir, |
941 | LogDir: environs.LogDir, |
942 | CloudInitOutputLog: environs.CloudInitOutputLog, |
943 | - RsyslogConfPath: environs.RsyslogConfPath, |
944 | Tools: &tools.Tools{URL: "file://" + c.MkDir()}, |
945 | StateInfo: &state.Info{ |
946 | CACert: []byte(testing.CACert), |
947 | @@ -46,7 +45,6 @@ |
948 | Addrs: []string{"127.0.0.1:123"}, |
949 | Tag: names.MachineTag(machineID), |
950 | }, |
951 | - SyslogPort: 2345, |
952 | MachineAgentServiceName: "jujud-machine-0", |
953 | } |
954 | } |
955 | |
956 | === modified file 'provider/local/config.go' |
957 | --- provider/local/config.go 2014-02-12 02:56:13 +0000 |
958 | +++ provider/local/config.go 2014-02-25 14:03:09 +0000 |
959 | @@ -107,7 +107,6 @@ |
960 | for _, dirname := range []string{ |
961 | c.storageDir(), |
962 | c.mongoDir(), |
963 | - c.logDir(), |
964 | } { |
965 | logger.Tracef("creating directory %s", dirname) |
966 | if err := os.MkdirAll(dirname, 0755); err != nil { |
967 | |
968 | === modified file 'provider/local/environ.go' |
969 | --- provider/local/environ.go 2014-02-20 08:23:40 +0000 |
970 | +++ provider/local/environ.go 2014-02-25 14:03:09 +0000 |
971 | @@ -138,9 +138,8 @@ |
972 | mcfg := environs.NewBootstrapMachineConfig(stateFileURL, privateKey) |
973 | mcfg.Tools = selectedTools[0] |
974 | mcfg.DataDir = env.config.rootDir() |
975 | - mcfg.LogDir = env.config.logDir() |
976 | - mcfg.RsyslogConfPath = env.rsyslogConfPath() |
977 | - mcfg.CloudInitOutputLog = filepath.Join(mcfg.LogDir, "cloud-init-output.log") |
978 | + mcfg.LogDir = fmt.Sprintf("/var/log/juju-%s", env.config.namespace()) |
979 | + mcfg.CloudInitOutputLog = filepath.Join(env.config.logDir(), "cloud-init-output.log") |
980 | mcfg.DisablePackageCommands = true |
981 | mcfg.MachineAgentServiceName = env.machineAgentServiceName() |
982 | mcfg.MongoServiceName = env.mongoServiceName() |
983 | @@ -162,10 +161,14 @@ |
984 | // Also, we leave the old all-machines.log file in |
985 | // /var/log/juju-{{namespace}} until we start the environment again. So |
986 | // potentially remove it at the start of the cloud-init. |
987 | - logfile := fmt.Sprintf("/var/log/juju-%s/all-machines.log", env.config.namespace()) |
988 | + os.RemoveAll(env.config.logDir()) |
989 | + os.MkdirAll(env.config.logDir(), 0755) |
990 | cloudcfg.AddScripts( |
991 | - fmt.Sprintf("[ -f %s ] && rm %s", logfile, logfile), |
992 | - fmt.Sprintf("ln -s %s %s/", logfile, env.config.logDir())) |
993 | + fmt.Sprintf("rm -fr %s", mcfg.LogDir), |
994 | + fmt.Sprintf("mkdir -p %s", mcfg.LogDir), |
995 | + fmt.Sprintf("rm -f /var/spool/rsyslog/machine-0-%s", env.config.namespace()), |
996 | + fmt.Sprintf("ln -s %s/all-machines.log %s/", mcfg.LogDir, env.config.logDir()), |
997 | + fmt.Sprintf("ln -s %s/machine-0.log %s/", env.config.logDir(), mcfg.LogDir)) |
998 | if err := cloudinit.ConfigureJuju(mcfg, cloudcfg); err != nil { |
999 | return err |
1000 | } |
1001 | |
1002 | === modified file 'provider/local/environprovider.go' |
1003 | --- provider/local/environprovider.go 2014-02-18 01:29:47 +0000 |
1004 | +++ provider/local/environprovider.go 2014-02-25 14:03:09 +0000 |
1005 | @@ -101,9 +101,10 @@ |
1006 | if err != nil { |
1007 | return nil, err |
1008 | } |
1009 | + attrs := make(map[string]interface{}) |
1010 | + |
1011 | // If the user has specified no values for any of the three normal |
1012 | // proxies, then look in the environment and set them. |
1013 | - attrs := make(map[string]interface{}) |
1014 | setIfNotBlank := func(key, value string) { |
1015 | if value != "" { |
1016 | attrs[key] = value |
1017 | @@ -130,13 +131,11 @@ |
1018 | setIfNotBlank("apt-https-proxy", proxy.Https) |
1019 | setIfNotBlank("apt-ftp-proxy", proxy.Ftp) |
1020 | } |
1021 | - if len(attrs) > 0 { |
1022 | - cfg, err = cfg.Apply(attrs) |
1023 | - if err != nil { |
1024 | - return nil, err |
1025 | - } |
1026 | - } |
1027 | |
1028 | + cfg, err = cfg.Apply(attrs) |
1029 | + if err != nil { |
1030 | + return nil, err |
1031 | + } |
1032 | return p.Open(cfg) |
1033 | } |
1034 | |
1035 | |
1036 | === modified file 'state/address.go' |
1037 | --- state/address.go 2014-01-22 19:28:08 +0000 |
1038 | +++ state/address.go 2014-02-25 14:03:09 +0000 |
1039 | @@ -122,7 +122,6 @@ |
1040 | type DeployerConnectionValues struct { |
1041 | StateAddresses []string |
1042 | APIAddresses []string |
1043 | - SyslogPort int |
1044 | } |
1045 | |
1046 | // DeployerConnectionInfo returns the address information necessary for the deployer. |
1047 | @@ -139,6 +138,5 @@ |
1048 | return &DeployerConnectionValues{ |
1049 | StateAddresses: appendPort(addrs, config.StatePort()), |
1050 | APIAddresses: appendPort(addrs, config.APIPort()), |
1051 | - SyslogPort: config.SyslogPort(), |
1052 | }, nil |
1053 | } |
1054 | |
1055 | === modified file 'state/api/params/params.go' |
1056 | --- state/api/params/params.go 2014-01-31 03:36:58 +0000 |
1057 | +++ state/api/params/params.go 2014-02-25 14:03:09 +0000 |
1058 | @@ -513,7 +513,6 @@ |
1059 | ProviderType string |
1060 | AuthorizedKeys string |
1061 | SSLHostnameVerification bool |
1062 | - SyslogPort int |
1063 | Proxy osenv.ProxySettings |
1064 | AptProxy osenv.ProxySettings |
1065 | } |
1066 | @@ -562,10 +561,14 @@ |
1067 | type DeployerConnectionValues struct { |
1068 | StateAddresses []string |
1069 | APIAddresses []string |
1070 | - SyslogPort int |
1071 | } |
1072 | |
1073 | // StatusParams holds parameters for the Status call. |
1074 | type StatusParams struct { |
1075 | Patterns []string |
1076 | } |
1077 | + |
1078 | +// SetRsyslogCertParams holds parameters for the SetRsyslogCert call. |
1079 | +type SetRsyslogCertParams struct { |
1080 | + CACert []byte |
1081 | +} |
1082 | |
1083 | === modified file 'state/api/provisioner/provisioner_test.go' |
1084 | --- state/api/provisioner/provisioner_test.go 2014-02-14 11:33:57 +0000 |
1085 | +++ state/api/provisioner/provisioner_test.go 2014-02-25 14:03:09 +0000 |
1086 | @@ -358,7 +358,6 @@ |
1087 | c.Assert(result.ProviderType, gc.Equals, "dummy") |
1088 | c.Assert(result.AuthorizedKeys, gc.Equals, coretesting.FakeAuthKeys) |
1089 | c.Assert(result.SSLHostnameVerification, jc.IsTrue) |
1090 | - c.Assert(result.SyslogPort, gc.Equals, 2345) |
1091 | } |
1092 | |
1093 | func (s *provisionerSuite) TestCACert(c *gc.C) { |
1094 | |
1095 | === added directory 'state/api/rsyslog' |
1096 | === added file 'state/api/rsyslog/package_test.go' |
1097 | --- state/api/rsyslog/package_test.go 1970-01-01 00:00:00 +0000 |
1098 | +++ state/api/rsyslog/package_test.go 2014-02-25 14:03:09 +0000 |
1099 | @@ -0,0 +1,14 @@ |
1100 | +// Copyright 2014 Canonical Ltd. |
1101 | +// Licensed under the AGPLv3, see LICENCE file for details. |
1102 | + |
1103 | +package rsyslog_test |
1104 | + |
1105 | +import ( |
1106 | + stdtesting "testing" |
1107 | + |
1108 | + "launchpad.net/juju-core/testing" |
1109 | +) |
1110 | + |
1111 | +func TestAll(t *stdtesting.T) { |
1112 | + testing.MgoTestPackage(t) |
1113 | +} |
1114 | |
1115 | === added file 'state/api/rsyslog/rsyslog.go' |
1116 | --- state/api/rsyslog/rsyslog.go 1970-01-01 00:00:00 +0000 |
1117 | +++ state/api/rsyslog/rsyslog.go 2014-02-25 14:03:09 +0000 |
1118 | @@ -0,0 +1,44 @@ |
1119 | +// Copyright 2014 Canonical Ltd. |
1120 | +// Licensed under the AGPLv3, see LICENCE file for details. |
1121 | + |
1122 | +package rsyslog |
1123 | + |
1124 | +import ( |
1125 | + "launchpad.net/juju-core/state/api/base" |
1126 | + "launchpad.net/juju-core/state/api/common" |
1127 | + "launchpad.net/juju-core/state/api/params" |
1128 | +) |
1129 | + |
1130 | +const rsyslogAPI = "Rsyslog" |
1131 | + |
1132 | +// State provides access to the Rsyslog API facade. |
1133 | +type State struct { |
1134 | + *common.EnvironWatcher |
1135 | + caller base.Caller |
1136 | +} |
1137 | + |
1138 | +// NewState creates a new client-side Rsyslog facade. |
1139 | +func NewState(caller base.Caller) *State { |
1140 | + return &State{ |
1141 | + EnvironWatcher: common.NewEnvironWatcher(rsyslogAPI, caller), |
1142 | + caller: caller, |
1143 | + } |
1144 | +} |
1145 | + |
1146 | +// SetRsyslogCert sets the rsyslog CA certificate, |
1147 | +// which is used by clients to verify the server's |
1148 | +// identity and establish a TLS session. |
1149 | +func (st *State) SetRsyslogCert(caCert []byte) error { |
1150 | + var result params.ErrorResult |
1151 | + args := params.SetRsyslogCertParams{ |
1152 | + CACert: caCert, |
1153 | + } |
1154 | + err := st.caller.Call(rsyslogAPI, "", "SetRsyslogCert", args, &result) |
1155 | + if err != nil { |
1156 | + return err |
1157 | + } |
1158 | + if result.Error != nil { |
1159 | + return result.Error |
1160 | + } |
1161 | + return nil |
1162 | +} |
1163 | |
1164 | === added file 'state/api/rsyslog/rsyslog_test.go' |
1165 | --- state/api/rsyslog/rsyslog_test.go 1970-01-01 00:00:00 +0000 |
1166 | +++ state/api/rsyslog/rsyslog_test.go 2014-02-25 14:03:09 +0000 |
1167 | @@ -0,0 +1,33 @@ |
1168 | +// Copyright 2014 Canonical Ltd. |
1169 | +// Licensed under the AGPLv3, see LICENCE file for details. |
1170 | + |
1171 | +package rsyslog_test |
1172 | + |
1173 | +import ( |
1174 | + gc "launchpad.net/gocheck" |
1175 | + |
1176 | + jujutesting "launchpad.net/juju-core/juju/testing" |
1177 | + commontesting "launchpad.net/juju-core/state/api/common/testing" |
1178 | +) |
1179 | + |
1180 | +type rsyslogSuite struct { |
1181 | + jujutesting.JujuConnSuite |
1182 | + *commontesting.EnvironWatcherTest |
1183 | +} |
1184 | + |
1185 | +var _ = gc.Suite(&rsyslogSuite{}) |
1186 | + |
1187 | +func (s *rsyslogSuite) SetUpTest(c *gc.C) { |
1188 | + s.JujuConnSuite.SetUpTest(c) |
1189 | + |
1190 | + stateAPI, _ := s.OpenAPIAsNewMachine(c) |
1191 | + rsyslogAPI := stateAPI.Rsyslog() |
1192 | + c.Assert(rsyslogAPI, gc.NotNil) |
1193 | + |
1194 | + s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest( |
1195 | + rsyslogAPI, |
1196 | + s.State, |
1197 | + s.BackingState, |
1198 | + commontesting.NoSecrets, |
1199 | + ) |
1200 | +} |
1201 | |
1202 | === modified file 'state/api/state.go' |
1203 | --- state/api/state.go 2014-02-18 00:15:30 +0000 |
1204 | +++ state/api/state.go 2014-02-25 14:03:09 +0000 |
1205 | @@ -14,6 +14,7 @@ |
1206 | "launchpad.net/juju-core/state/api/machiner" |
1207 | "launchpad.net/juju-core/state/api/params" |
1208 | "launchpad.net/juju-core/state/api/provisioner" |
1209 | + "launchpad.net/juju-core/state/api/rsyslog" |
1210 | "launchpad.net/juju-core/state/api/uniter" |
1211 | "launchpad.net/juju-core/state/api/upgrader" |
1212 | ) |
1213 | @@ -99,3 +100,8 @@ |
1214 | func (st *State) CharmRevisionUpdater() *charmrevisionupdater.State { |
1215 | return charmrevisionupdater.NewState(st) |
1216 | } |
1217 | + |
1218 | +// Rsyslog returns access to the Rsyslog API |
1219 | +func (st *State) Rsyslog() *rsyslog.State { |
1220 | + return rsyslog.NewState(st) |
1221 | +} |
1222 | |
1223 | === modified file 'state/apiserver/deployer/deployer.go' |
1224 | --- state/apiserver/deployer/deployer.go 2014-01-21 15:54:31 +0000 |
1225 | +++ state/apiserver/deployer/deployer.go 2014-02-25 14:03:09 +0000 |
1226 | @@ -76,7 +76,6 @@ |
1227 | result = params.DeployerConnectionValues{ |
1228 | StateAddresses: info.StateAddresses, |
1229 | APIAddresses: info.APIAddresses, |
1230 | - SyslogPort: info.SyslogPort, |
1231 | } |
1232 | } |
1233 | return result, err |
1234 | |
1235 | === modified file 'state/apiserver/provisioner/provisioner.go' |
1236 | --- state/apiserver/provisioner/provisioner.go 2014-01-31 03:36:58 +0000 |
1237 | +++ state/apiserver/provisioner/provisioner.go 2014-02-25 14:03:09 +0000 |
1238 | @@ -196,7 +196,6 @@ |
1239 | result.ProviderType = config.Type() |
1240 | result.AuthorizedKeys = config.AuthorizedKeys() |
1241 | result.SSLHostnameVerification = config.SSLHostnameVerification() |
1242 | - result.SyslogPort = config.SyslogPort() |
1243 | result.Proxy = config.ProxySettings() |
1244 | result.AptProxy = config.AptProxySettings() |
1245 | return result, nil |
1246 | |
1247 | === modified file 'state/apiserver/provisioner/provisioner_test.go' |
1248 | --- state/apiserver/provisioner/provisioner_test.go 2014-02-14 11:33:57 +0000 |
1249 | +++ state/apiserver/provisioner/provisioner_test.go 2014-02-25 14:03:09 +0000 |
1250 | @@ -700,7 +700,6 @@ |
1251 | c.Check(results.ProviderType, gc.Equals, "dummy") |
1252 | c.Check(results.AuthorizedKeys, gc.Equals, coretesting.FakeAuthKeys) |
1253 | c.Check(results.SSLHostnameVerification, jc.IsTrue) |
1254 | - c.Check(results.SyslogPort, gc.Equals, 2345) |
1255 | c.Check(results.Proxy, gc.DeepEquals, expectedProxy) |
1256 | c.Check(results.AptProxy, gc.DeepEquals, expectedProxy) |
1257 | } |
1258 | |
1259 | === modified file 'state/apiserver/root.go' |
1260 | --- state/apiserver/root.go 2014-02-20 03:12:23 +0000 |
1261 | +++ state/apiserver/root.go 2014-02-25 14:03:09 +0000 |
1262 | @@ -24,6 +24,7 @@ |
1263 | loggerapi "launchpad.net/juju-core/state/apiserver/logger" |
1264 | "launchpad.net/juju-core/state/apiserver/machine" |
1265 | "launchpad.net/juju-core/state/apiserver/provisioner" |
1266 | + "launchpad.net/juju-core/state/apiserver/rsyslog" |
1267 | "launchpad.net/juju-core/state/apiserver/uniter" |
1268 | "launchpad.net/juju-core/state/apiserver/upgrader" |
1269 | "launchpad.net/juju-core/state/multiwatcher" |
1270 | @@ -182,6 +183,17 @@ |
1271 | return environment.NewEnvironmentAPI(r.srv.state, r.resources, r) |
1272 | } |
1273 | |
1274 | +// Rsyslog returns an object that provides access to the Rsyslog API |
1275 | +// facade. The id argument is reserved for future use and currently needs to |
1276 | +// be empty. |
1277 | +func (r *srvRoot) Rsyslog(id string) (*rsyslog.RsyslogAPI, error) { |
1278 | + if id != "" { |
1279 | + // Safeguard id for possible future use. |
1280 | + return nil, common.ErrBadId |
1281 | + } |
1282 | + return rsyslog.NewRsyslogAPI(r.srv.state, r.resources, r) |
1283 | +} |
1284 | + |
1285 | // Logger returns an object that provides access to the Logger API facade. |
1286 | // The id argument is reserved for future use and must be empty. |
1287 | func (r *srvRoot) Logger(id string) (*loggerapi.LoggerAPI, error) { |
1288 | |
1289 | === added directory 'state/apiserver/rsyslog' |
1290 | === added file 'state/apiserver/rsyslog/package_test.go' |
1291 | --- state/apiserver/rsyslog/package_test.go 1970-01-01 00:00:00 +0000 |
1292 | +++ state/apiserver/rsyslog/package_test.go 2014-02-25 14:03:09 +0000 |
1293 | @@ -0,0 +1,14 @@ |
1294 | +// Copyright 2014 Canonical Ltd. |
1295 | +// Licensed under the AGPLv3, see LICENCE file for details. |
1296 | + |
1297 | +package rsyslog_test |
1298 | + |
1299 | +import ( |
1300 | + stdtesting "testing" |
1301 | + |
1302 | + "launchpad.net/juju-core/testing" |
1303 | +) |
1304 | + |
1305 | +func TestAll(t *stdtesting.T) { |
1306 | + testing.MgoTestPackage(t) |
1307 | +} |
1308 | |
1309 | === added file 'state/apiserver/rsyslog/rsyslog.go' |
1310 | --- state/apiserver/rsyslog/rsyslog.go 1970-01-01 00:00:00 +0000 |
1311 | +++ state/apiserver/rsyslog/rsyslog.go 2014-02-25 14:03:09 +0000 |
1312 | @@ -0,0 +1,56 @@ |
1313 | +// Copyright 2014 Canonical Ltd. |
1314 | +// Licensed under the AGPLv3, see LICENCE file for details. |
1315 | + |
1316 | +package rsyslog |
1317 | + |
1318 | +import ( |
1319 | + "launchpad.net/juju-core/cert" |
1320 | + "launchpad.net/juju-core/state" |
1321 | + "launchpad.net/juju-core/state/api/params" |
1322 | + "launchpad.net/juju-core/state/apiserver/common" |
1323 | +) |
1324 | + |
1325 | +// RsyslogAPI implements the API used by the rsyslog worker. |
1326 | +type RsyslogAPI struct { |
1327 | + *common.EnvironWatcher |
1328 | + st *state.State |
1329 | + canModify bool |
1330 | +} |
1331 | + |
1332 | +// NewRsyslogAPI creates a new instance of the Rsyslog API. |
1333 | +func NewRsyslogAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*RsyslogAPI, error) { |
1334 | + // Can always watch for environ changes. |
1335 | + getCanWatch := common.AuthAlways(true) |
1336 | + // Does not get the secrets. |
1337 | + getCanReadSecrets := common.AuthAlways(false) |
1338 | + return &RsyslogAPI{ |
1339 | + EnvironWatcher: common.NewEnvironWatcher(st, resources, getCanWatch, getCanReadSecrets), |
1340 | + st: st, |
1341 | + canModify: authorizer.AuthEnvironManager(), |
1342 | + }, nil |
1343 | +} |
1344 | + |
1345 | +func (api *RsyslogAPI) SetRsyslogCert(args params.SetRsyslogCertParams) (params.ErrorResult, error) { |
1346 | + var result params.ErrorResult |
1347 | + if !api.canModify { |
1348 | + result.Error = common.ServerError(common.ErrBadCreds) |
1349 | + return result, nil |
1350 | + } |
1351 | + if _, err := cert.ParseCert(args.CACert); err != nil { |
1352 | + result.Error = common.ServerError(err) |
1353 | + return result, nil |
1354 | + } |
1355 | + old, err := api.st.EnvironConfig() |
1356 | + if err != nil { |
1357 | + return params.ErrorResult{}, err |
1358 | + } |
1359 | + cfg, err := old.Apply(map[string]interface{}{"rsyslog-ca-cert": string(args.CACert)}) |
1360 | + if err != nil { |
1361 | + result.Error = common.ServerError(err) |
1362 | + } else { |
1363 | + if err := api.st.SetEnvironConfig(cfg, old); err != nil { |
1364 | + result.Error = common.ServerError(err) |
1365 | + } |
1366 | + } |
1367 | + return result, nil |
1368 | +} |
1369 | |
1370 | === added file 'state/apiserver/rsyslog/rsyslog_test.go' |
1371 | --- state/apiserver/rsyslog/rsyslog_test.go 1970-01-01 00:00:00 +0000 |
1372 | +++ state/apiserver/rsyslog/rsyslog_test.go 2014-02-25 14:03:09 +0000 |
1373 | @@ -0,0 +1,48 @@ |
1374 | +// Copyright 2013 Canonical Ltd. |
1375 | +// Licensed under the AGPLv3, see LICENCE file for details. |
1376 | + |
1377 | +package rsyslog_test |
1378 | + |
1379 | +import ( |
1380 | + gc "launchpad.net/gocheck" |
1381 | + |
1382 | + "launchpad.net/juju-core/juju/testing" |
1383 | + "launchpad.net/juju-core/state/apiserver/common" |
1384 | + commontesting "launchpad.net/juju-core/state/apiserver/common/testing" |
1385 | + "launchpad.net/juju-core/state/apiserver/rsyslog" |
1386 | + apiservertesting "launchpad.net/juju-core/state/apiserver/testing" |
1387 | +) |
1388 | + |
1389 | +type rsyslogSuite struct { |
1390 | + testing.JujuConnSuite |
1391 | + *commontesting.EnvironWatcherTest |
1392 | + authorizer apiservertesting.FakeAuthorizer |
1393 | + resources *common.Resources |
1394 | +} |
1395 | + |
1396 | +var _ = gc.Suite(&rsyslogSuite{}) |
1397 | + |
1398 | +func (s *rsyslogSuite) SetUpTest(c *gc.C) { |
1399 | + s.JujuConnSuite.SetUpTest(c) |
1400 | + s.authorizer = apiservertesting.FakeAuthorizer{ |
1401 | + LoggedIn: true, |
1402 | + EnvironManager: true, |
1403 | + } |
1404 | + s.resources = common.NewResources() |
1405 | + api, err := rsyslog.NewRsyslogAPI(s.State, s.resources, s.authorizer) |
1406 | + c.Assert(err, gc.IsNil) |
1407 | + s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest( |
1408 | + api, s.State, s.resources, commontesting.NoSecrets) |
1409 | +} |
1410 | + |
1411 | +func (s *rsyslogSuite) TestSetRsyslogCert(c *gc.C) { |
1412 | + st := s.APIState.Rsyslog() |
1413 | + err := st.SetRsyslogCert(nil) |
1414 | + // TODO(axw) finish me. this should fail due to being an invalid cert |
1415 | + c.Assert(err, gc.IsNil) |
1416 | +} |
1417 | + |
1418 | +func (s *rsyslogSuite) TestSetRsyslogCertPerms(c *gc.C) { |
1419 | + // TODO(axw) SetRsyslogCert requires that the |
1420 | + // caller is a state server. |
1421 | +} |
1422 | |
1423 | === modified file 'upgrades/export_test.go' |
1424 | --- upgrades/export_test.go 2014-02-13 05:22:01 +0000 |
1425 | +++ upgrades/export_test.go 2014-02-25 14:03:09 +0000 |
1426 | @@ -10,6 +10,4 @@ |
1427 | // 118 upgrade functions |
1428 | StepsFor118 = stepsFor118 |
1429 | EnsureLockDirExistsAndUbuntuWritable = ensureLockDirExistsAndUbuntuWritable |
1430 | - UpgradeStateServerRsyslogConfig = upgradeStateServerRsyslogConfig |
1431 | - UpgradeHostMachineRsyslogConfig = upgradeHostMachineRsyslogConfig |
1432 | ) |
1433 | |
1434 | === removed file 'upgrades/rsyslogconf.go' |
1435 | --- upgrades/rsyslogconf.go 2014-02-14 00:48:23 +0000 |
1436 | +++ upgrades/rsyslogconf.go 1970-01-01 00:00:00 +0000 |
1437 | @@ -1,50 +0,0 @@ |
1438 | -// Copyright 2014 Canonical Ltd. |
1439 | -// Licensed under the AGPLv3, see LICENCE file for details. |
1440 | - |
1441 | -package upgrades |
1442 | - |
1443 | -import ( |
1444 | - "launchpad.net/juju-core/agent" |
1445 | - "launchpad.net/juju-core/environs" |
1446 | - "launchpad.net/juju-core/log/syslog" |
1447 | -) |
1448 | - |
1449 | -func confParams(context Context) (machineTag, namespace string, port int, err error) { |
1450 | - namespace = context.AgentConfig().Value(agent.Namespace) |
1451 | - machineTag = context.AgentConfig().Tag() |
1452 | - |
1453 | - environment := context.APIState().Environment() |
1454 | - config, err := environment.EnvironConfig() |
1455 | - if err != nil { |
1456 | - return "", "", 0, err |
1457 | - } |
1458 | - port = config.SyslogPort() |
1459 | - return machineTag, namespace, port, err |
1460 | -} |
1461 | - |
1462 | -// upgradeStateServerRsyslogConfig upgrades a rsuslog config file on a state server. |
1463 | -func upgradeStateServerRsyslogConfig(context Context) (err error) { |
1464 | - machineTag, namespace, syslogPort, err := confParams(context) |
1465 | - configRenderer := syslog.NewAccumulateConfig(machineTag, syslogPort, namespace) |
1466 | - data, err := configRenderer.Render() |
1467 | - if err != nil { |
1468 | - return nil |
1469 | - } |
1470 | - return WriteReplacementFile(environs.RsyslogConfPath, []byte(data), 0644) |
1471 | -} |
1472 | - |
1473 | -// upgradeHostMachineRsyslogConfig upgrades a rsuslog config file on a host machine. |
1474 | -func upgradeHostMachineRsyslogConfig(context Context) (err error) { |
1475 | - machineTag, namespace, syslogPort, err := confParams(context) |
1476 | - addr, err := context.AgentConfig().APIAddresses() |
1477 | - if err != nil { |
1478 | - return err |
1479 | - } |
1480 | - |
1481 | - configRenderer := syslog.NewForwardConfig(machineTag, syslogPort, namespace, addr) |
1482 | - data, err := configRenderer.Render() |
1483 | - if err != nil { |
1484 | - return nil |
1485 | - } |
1486 | - return WriteReplacementFile(environs.RsyslogConfPath, []byte(data), 0644) |
1487 | -} |
1488 | |
1489 | === removed file 'upgrades/rsyslogconf_test.go' |
1490 | --- upgrades/rsyslogconf_test.go 2014-02-14 11:39:37 +0000 |
1491 | +++ upgrades/rsyslogconf_test.go 1970-01-01 00:00:00 +0000 |
1492 | @@ -1,72 +0,0 @@ |
1493 | -// Copyright 2014 Canonical Ltd. |
1494 | -// Licensed under the AGPLv3, see LICENCE file for details. |
1495 | - |
1496 | -package upgrades_test |
1497 | - |
1498 | -import ( |
1499 | - "io/ioutil" |
1500 | - "path/filepath" |
1501 | - |
1502 | - gc "launchpad.net/gocheck" |
1503 | - |
1504 | - "launchpad.net/juju-core/environs" |
1505 | - jujutesting "launchpad.net/juju-core/juju/testing" |
1506 | - syslogtesting "launchpad.net/juju-core/log/syslog/testing" |
1507 | - "launchpad.net/juju-core/state" |
1508 | - "launchpad.net/juju-core/upgrades" |
1509 | -) |
1510 | - |
1511 | -type rsyslogSuite struct { |
1512 | - jujutesting.JujuConnSuite |
1513 | - |
1514 | - syslogPath string |
1515 | - ctx upgrades.Context |
1516 | -} |
1517 | - |
1518 | -var _ = gc.Suite(&rsyslogSuite{}) |
1519 | - |
1520 | -func (s *rsyslogSuite) SetUpTest(c *gc.C) { |
1521 | - s.JujuConnSuite.SetUpTest(c) |
1522 | - |
1523 | - dir := c.MkDir() |
1524 | - s.syslogPath = filepath.Join(dir, "fakesyslog.conf") |
1525 | - s.PatchValue(&environs.RsyslogConfPath, s.syslogPath) |
1526 | - |
1527 | - apiState, _ := s.OpenAPIAsNewMachine(c, state.JobManageEnviron) |
1528 | - s.ctx = &mockContext{ |
1529 | - agentConfig: &mockAgentConfig{ |
1530 | - tag: "machine-tag", |
1531 | - namespace: "namespace", |
1532 | - apiAddresses: []string{"server:1234"}, |
1533 | - }, |
1534 | - apiState: apiState, |
1535 | - } |
1536 | -} |
1537 | - |
1538 | -func (s *rsyslogSuite) TestStateServerUpgrade(c *gc.C) { |
1539 | - err := upgrades.UpgradeStateServerRsyslogConfig(s.ctx) |
1540 | - c.Assert(err, gc.IsNil) |
1541 | - |
1542 | - data, err := ioutil.ReadFile(s.syslogPath) |
1543 | - c.Assert(err, gc.IsNil) |
1544 | - c.Assert(string(data), gc.Equals, syslogtesting.ExpectedAccumulateSyslogConf(c, "machine-tag", "namespace", 2345)) |
1545 | -} |
1546 | - |
1547 | -func (s *rsyslogSuite) TestStateServerUpgradeIdempotent(c *gc.C) { |
1548 | - s.TestStateServerUpgrade(c) |
1549 | - s.TestStateServerUpgrade(c) |
1550 | -} |
1551 | - |
1552 | -func (s *rsyslogSuite) TestHostMachineUpgrade(c *gc.C) { |
1553 | - err := upgrades.UpgradeHostMachineRsyslogConfig(s.ctx) |
1554 | - c.Assert(err, gc.IsNil) |
1555 | - |
1556 | - data, err := ioutil.ReadFile(s.syslogPath) |
1557 | - c.Assert(err, gc.IsNil) |
1558 | - c.Assert(string(data), gc.Equals, syslogtesting.ExpectedForwardSyslogConf(c, "machine-tag", "namespace", 2345)) |
1559 | -} |
1560 | - |
1561 | -func (s *rsyslogSuite) TestHostServerUpgradeIdempotent(c *gc.C) { |
1562 | - s.TestHostMachineUpgrade(c) |
1563 | - s.TestHostMachineUpgrade(c) |
1564 | -} |
1565 | |
1566 | === modified file 'upgrades/steps118.go' |
1567 | --- upgrades/steps118.go 2014-02-16 23:35:10 +0000 |
1568 | +++ upgrades/steps118.go 2014-02-25 14:03:09 +0000 |
1569 | @@ -11,15 +11,5 @@ |
1570 | targets: []Target{HostMachine}, |
1571 | run: ensureLockDirExistsAndUbuntuWritable, |
1572 | }, |
1573 | - &upgradeStep{ |
1574 | - description: "upgrade rsyslog config file on state server", |
1575 | - targets: []Target{StateServer}, |
1576 | - run: upgradeStateServerRsyslogConfig, |
1577 | - }, |
1578 | - &upgradeStep{ |
1579 | - description: "upgrade rsyslog config file on host machine", |
1580 | - targets: []Target{HostMachine}, |
1581 | - run: upgradeHostMachineRsyslogConfig, |
1582 | - }, |
1583 | } |
1584 | } |
1585 | |
1586 | === modified file 'upgrades/steps118_test.go' |
1587 | --- upgrades/steps118_test.go 2014-02-13 05:22:01 +0000 |
1588 | +++ upgrades/steps118_test.go 2014-02-25 14:03:09 +0000 |
1589 | @@ -18,12 +18,10 @@ |
1590 | |
1591 | var expectedSteps = []string{ |
1592 | "make $DATADIR/locks owned by ubuntu:ubuntu", |
1593 | - "upgrade rsyslog config file on state server", |
1594 | - "upgrade rsyslog config file on host machine", |
1595 | } |
1596 | |
1597 | func (s *steps118Suite) TestUpgradeOperationsContent(c *gc.C) { |
1598 | upgradeSteps := upgrades.StepsFor118() |
1599 | - c.Assert(upgradeSteps, gc.HasLen, 3) |
1600 | + c.Assert(upgradeSteps, gc.HasLen, 1) |
1601 | assertExpectedSteps(c, upgradeSteps, expectedSteps) |
1602 | } |
1603 | |
1604 | === modified file 'worker/deployer/export_test.go' |
1605 | --- worker/deployer/export_test.go 2013-11-25 03:52:09 +0000 |
1606 | +++ worker/deployer/export_test.go 2014-02-25 14:03:09 +0000 |
1607 | @@ -12,9 +12,8 @@ |
1608 | |
1609 | func (*fakeAPI) ConnectionInfo() (params.DeployerConnectionValues, error) { |
1610 | return params.DeployerConnectionValues{ |
1611 | - []string{"s1:123", "s2:123"}, |
1612 | - []string{"a1:123", "a2:123"}, |
1613 | - 2345, |
1614 | + StateAddresses: []string{"s1:123", "s2:123"}, |
1615 | + APIAddresses: []string{"a1:123", "a2:123"}, |
1616 | }, nil |
1617 | } |
1618 | |
1619 | |
1620 | === modified file 'worker/deployer/simple.go' |
1621 | --- worker/deployer/simple.go 2014-02-12 07:24:47 +0000 |
1622 | +++ worker/deployer/simple.go 2014-02-25 14:03:09 +0000 |
1623 | @@ -54,9 +54,6 @@ |
1624 | // will be written. It is set for testing and left empty for production, in |
1625 | // which case the system default is used, typically /etc/rsyslog.d |
1626 | syslogConfigDir string |
1627 | - |
1628 | - // syslogConfigPath is the full path name of the syslog conf file. |
1629 | - syslogConfigPath string |
1630 | } |
1631 | |
1632 | var _ Context = (*SimpleContext)(nil) |
1633 | @@ -100,6 +97,7 @@ |
1634 | logger.Debugf("API addresses: %q", result.APIAddresses) |
1635 | containerType := ctx.agentConfig.Value(agent.ContainerType) |
1636 | namespace := ctx.agentConfig.Value(agent.Namespace) |
1637 | + // TODO(axw) record rsyslog config dir. |
1638 | conf, err := agent.NewAgentConfig( |
1639 | agent.AgentConfigParams{ |
1640 | DataDir: dataDir, |
1641 | @@ -125,18 +123,6 @@ |
1642 | |
1643 | // Install an upstart job that runs the unit agent. |
1644 | logPath := path.Join(ctx.logDir, tag+".log") |
1645 | - syslogConfigRenderer := syslog.NewForwardConfig(tag, result.SyslogPort, namespace, result.StateAddresses) |
1646 | - syslogConfigRenderer.ConfigDir = ctx.syslogConfigDir |
1647 | - syslogConfigRenderer.ConfigFileName = fmt.Sprintf("26-juju-%s.conf", tag) |
1648 | - if err := syslogConfigRenderer.Write(); err != nil { |
1649 | - return err |
1650 | - } |
1651 | - ctx.syslogConfigPath = syslogConfigRenderer.ConfigFilePath() |
1652 | - if err := syslog.Restart(); err != nil { |
1653 | - logger.Warningf("installer: cannot restart syslog daemon: %v", err) |
1654 | - } |
1655 | - defer removeOnErr(&err, ctx.syslogConfigPath) |
1656 | - |
1657 | cmd := strings.Join([]string{ |
1658 | path.Join(toolsDir, "jujud"), "unit", |
1659 | "--data-dir", dataDir, |
1660 | @@ -190,9 +176,6 @@ |
1661 | if err := os.RemoveAll(agentDir); err != nil { |
1662 | return err |
1663 | } |
1664 | - if err := os.Remove(ctx.syslogConfigPath); err != nil && !os.IsNotExist(err) { |
1665 | - logger.Warningf("installer: cannot remove %q: %v", ctx.syslogConfigPath, err) |
1666 | - } |
1667 | // Defer this so a failure here does not impede the cleanup (as in tests). |
1668 | defer func() { |
1669 | if err := syslog.Restart(); err != nil { |
1670 | |
1671 | === modified file 'worker/deployer/simple_test.go' |
1672 | --- worker/deployer/simple_test.go 2013-11-21 03:22:49 +0000 |
1673 | +++ worker/deployer/simple_test.go 2014-02-25 14:03:09 +0000 |
1674 | @@ -198,12 +198,11 @@ |
1675 | return deployer.NewTestSimpleContext(config, fix.initDir, fix.logDir, fix.syslogConfigDir) |
1676 | } |
1677 | |
1678 | -func (fix *SimpleToolsFixture) paths(tag string) (confPath, agentDir, toolsDir, syslogConfPath string) { |
1679 | +func (fix *SimpleToolsFixture) paths(tag string) (confPath, agentDir, toolsDir string) { |
1680 | confName := fmt.Sprintf("jujud-%s.conf", tag) |
1681 | confPath = filepath.Join(fix.initDir, confName) |
1682 | agentDir = agent.Dir(fix.dataDir, tag) |
1683 | toolsDir = tools.ToolsDir(fix.dataDir, tag) |
1684 | - syslogConfPath = filepath.Join(fix.syslogConfigDir, fmt.Sprintf("26-juju-%s.conf", tag)) |
1685 | return |
1686 | } |
1687 | |
1688 | @@ -225,7 +224,7 @@ |
1689 | |
1690 | func (fix *SimpleToolsFixture) checkUnitInstalled(c *gc.C, name, password string) { |
1691 | tag := names.UnitTag(name) |
1692 | - uconfPath, _, toolsDir, syslogConfPath := fix.paths(tag) |
1693 | + uconfPath, _, toolsDir := fix.paths(tag) |
1694 | uconfData, err := ioutil.ReadFile(uconfPath) |
1695 | c.Assert(err, gc.IsNil) |
1696 | uconf := string(uconfData) |
1697 | @@ -261,20 +260,12 @@ |
1698 | jujudData, err := ioutil.ReadFile(jujudPath) |
1699 | c.Assert(err, gc.IsNil) |
1700 | c.Assert(string(jujudData), gc.Equals, fakeJujud) |
1701 | - |
1702 | - syslogConfData, err := ioutil.ReadFile(syslogConfPath) |
1703 | - c.Assert(err, gc.IsNil) |
1704 | - parts := strings.SplitN(name, "/", 2) |
1705 | - unitTag := fmt.Sprintf("unit-%s-%s", parts[0], parts[1]) |
1706 | - expectedSyslogConfReplaced := fmt.Sprintf(expectedSyslogConf, unitTag, unitTag, unitTag) |
1707 | - c.Assert(string(syslogConfData), gc.Equals, expectedSyslogConfReplaced) |
1708 | - |
1709 | } |
1710 | |
1711 | func (fix *SimpleToolsFixture) checkUnitRemoved(c *gc.C, name string) { |
1712 | tag := names.UnitTag(name) |
1713 | - confPath, agentDir, toolsDir, syslogConfPath := fix.paths(tag) |
1714 | - for _, path := range []string{confPath, agentDir, toolsDir, syslogConfPath} { |
1715 | + confPath, agentDir, toolsDir := fix.paths(tag) |
1716 | + for _, path := range []string{confPath, agentDir, toolsDir} { |
1717 | _, err := ioutil.ReadFile(path) |
1718 | if err == nil { |
1719 | c.Log("Warning: %q not removed as expected", path) |
1720 | |
1721 | === modified file 'worker/provisioner/kvm-broker.go' |
1722 | --- worker/provisioner/kvm-broker.go 2014-01-31 03:36:58 +0000 |
1723 | +++ worker/provisioner/kvm-broker.go 2014-02-25 14:03:09 +0000 |
1724 | @@ -84,7 +84,6 @@ |
1725 | config.ProviderType, |
1726 | config.AuthorizedKeys, |
1727 | config.SSLHostnameVerification, |
1728 | - config.SyslogPort, |
1729 | config.Proxy, |
1730 | config.AptProxy, |
1731 | ); err != nil { |
1732 | |
1733 | === modified file 'worker/provisioner/lxc-broker.go' |
1734 | --- worker/provisioner/lxc-broker.go 2014-01-31 03:36:58 +0000 |
1735 | +++ worker/provisioner/lxc-broker.go 2014-02-25 14:03:09 +0000 |
1736 | @@ -74,7 +74,6 @@ |
1737 | config.ProviderType, |
1738 | config.AuthorizedKeys, |
1739 | config.SSLHostnameVerification, |
1740 | - config.SyslogPort, |
1741 | config.Proxy, |
1742 | config.AptProxy, |
1743 | ); err != nil { |
1744 | |
1745 | === modified file 'worker/provisioner/lxc-broker_test.go' |
1746 | --- worker/provisioner/lxc-broker_test.go 2014-02-14 11:33:57 +0000 |
1747 | +++ worker/provisioner/lxc-broker_test.go 2014-02-25 14:03:09 +0000 |
1748 | @@ -285,6 +285,5 @@ |
1749 | return params.ContainerConfig{ |
1750 | ProviderType: "fake", |
1751 | AuthorizedKeys: coretesting.FakeAuthKeys, |
1752 | - SSLHostnameVerification: true, |
1753 | - SyslogPort: 2345}, nil |
1754 | + SSLHostnameVerification: true}, nil |
1755 | } |
1756 | |
1757 | === added directory 'worker/rsyslog' |
1758 | === added file 'worker/rsyslog/worker.go' |
1759 | --- worker/rsyslog/worker.go 1970-01-01 00:00:00 +0000 |
1760 | +++ worker/rsyslog/worker.go 2014-02-25 14:03:09 +0000 |
1761 | @@ -0,0 +1,245 @@ |
1762 | +// Copyright 2014 Canonical Ltd. |
1763 | +// Licensed under the AGPLv3, see LICENCE file for details. |
1764 | + |
1765 | +package rsyslog |
1766 | + |
1767 | +import ( |
1768 | + "fmt" |
1769 | + "io/ioutil" |
1770 | + "os" |
1771 | + "os/user" |
1772 | + "path/filepath" |
1773 | + "strconv" |
1774 | + "time" |
1775 | + |
1776 | + "github.com/errgo/errgo" |
1777 | + "github.com/loggo/loggo" |
1778 | + |
1779 | + "launchpad.net/juju-core/agent" |
1780 | + "launchpad.net/juju-core/cert" |
1781 | + "launchpad.net/juju-core/log/syslog" |
1782 | + "launchpad.net/juju-core/names" |
1783 | + apirsyslog "launchpad.net/juju-core/state/api/rsyslog" |
1784 | + "launchpad.net/juju-core/state/api/watcher" |
1785 | + "launchpad.net/juju-core/utils" |
1786 | + "launchpad.net/juju-core/worker" |
1787 | +) |
1788 | + |
1789 | +var logger = loggo.GetLogger("juju.worker.rsyslog") |
1790 | + |
1791 | +const rsyslogConfDir = "/etc/rsyslog.d" |
1792 | + |
1793 | +// RsyslogMode describes how to configure rsyslog. |
1794 | +type RsyslogMode int |
1795 | + |
1796 | +const ( |
1797 | + RsyslogModeInvalid RsyslogMode = iota |
1798 | + // RsyslogModeForwarding is the mode in which |
1799 | + // rsyslog will be configured to forward logging |
1800 | + // to state servers. |
1801 | + RsyslogModeForwarding |
1802 | + // RsyslogModeAccumulate is the mode in which |
1803 | + // rsyslog will be configured to accumulate logging |
1804 | + // from other machines into an "all-machines.log". |
1805 | + RsyslogModeAccumulate |
1806 | +) |
1807 | + |
1808 | +// RsyslogConfigHandler implements worker.NotifyWatchHandler, watching |
1809 | +// environment configuration changes and generating new rsyslog |
1810 | +// configuration. |
1811 | +type RsyslogConfigHandler struct { |
1812 | + st *apirsyslog.State |
1813 | + mode RsyslogMode |
1814 | + syslogConfig *syslog.SyslogConfig |
1815 | + rsyslogConfPath string |
1816 | + rsyslogGnutlsInstalled bool |
1817 | +} |
1818 | + |
1819 | +var _ worker.NotifyWatchHandler = (*RsyslogConfigHandler)(nil) |
1820 | + |
1821 | +// NewRsyslogConfigWorker returns a worker.Worker that watches |
1822 | +// for config changes and updates rsyslog configuration based |
1823 | +// on changes. |
1824 | +// NewRsyslogConfigWorker also returns the path to the rsyslog |
1825 | +// configuration file that is written, so that the agent may |
1826 | +// remove it on shutdown. |
1827 | +func NewRsyslogConfigWorker(st *apirsyslog.State, config agent.Config, mode RsyslogMode) (worker.Worker, error) { |
1828 | + namespace := config.Value(agent.Namespace) |
1829 | + var syslogConfig *syslog.SyslogConfig |
1830 | + if mode == RsyslogModeAccumulate { |
1831 | + syslogConfig = syslog.NewAccumulateConfig(config.Tag(), 0, namespace) |
1832 | + } else { |
1833 | + addr, err := config.APIAddresses() |
1834 | + if err != nil { |
1835 | + return nil, err |
1836 | + } |
1837 | + syslogConfig = syslog.NewForwardConfig(config.Tag(), 0, namespace, addr) |
1838 | + } |
1839 | + |
1840 | + // Historically only machine-0 includes the namespace in the log |
1841 | + // dir/file; for backwards compatibility we continue the tradition. |
1842 | + if config.Tag() != "machine-0" { |
1843 | + namespace = "" |
1844 | + } |
1845 | + kind, err := names.TagKind(config.Tag()) |
1846 | + if err != nil { |
1847 | + return nil, err |
1848 | + } |
1849 | + if kind == names.MachineTagKind { |
1850 | + if namespace == "" { |
1851 | + syslogConfig.ConfigFileName = "25-juju.conf" |
1852 | + } else { |
1853 | + syslogConfig.ConfigFileName = fmt.Sprintf("25-juju-%s.conf", namespace) |
1854 | + } |
1855 | + } else { |
1856 | + syslogConfig.ConfigFileName = fmt.Sprintf("26-juju-%s.conf", config.Tag()) |
1857 | + } |
1858 | + |
1859 | + if namespace != "" { |
1860 | + syslogConfig.LogDir += "-" + namespace |
1861 | + } |
1862 | + worker := worker.NewNotifyWorker(&RsyslogConfigHandler{ |
1863 | + st: st, |
1864 | + mode: mode, |
1865 | + syslogConfig: syslogConfig, |
1866 | + }) |
1867 | + return worker, nil |
1868 | +} |
1869 | + |
1870 | +func (h *RsyslogConfigHandler) SetUp() (watcher.NotifyWatcher, error) { |
1871 | + if h.mode == RsyslogModeAccumulate { |
1872 | + if err := h.ensureCertificates(); err != nil { |
1873 | + return nil, errgo.Annotate(err, "failed to write rsyslog certificates") |
1874 | + } |
1875 | + } |
1876 | + return h.st.WatchForEnvironConfigChanges() |
1877 | +} |
1878 | + |
1879 | +func (h *RsyslogConfigHandler) TearDown() error { |
1880 | + if err := os.Remove(h.syslogConfig.ConfigFilePath()); err == nil { |
1881 | + syslog.Restart() |
1882 | + } |
1883 | + return nil |
1884 | +} |
1885 | + |
1886 | +func (h *RsyslogConfigHandler) Handle() error { |
1887 | + if !h.rsyslogGnutlsInstalled { |
1888 | + if err := utils.AptGetInstall("rsyslog-gnutls"); err != nil { |
1889 | + // apt-get may fail if another process has the lock, |
1890 | + // so keep we'll just exit and try again next time. |
1891 | + return errgo.Annotate(err, "cannot install rsyslog-gnutls") |
1892 | + } |
1893 | + h.rsyslogGnutlsInstalled = true |
1894 | + } |
1895 | + cfg, err := h.st.EnvironConfig() |
1896 | + if err != nil { |
1897 | + return errgo.Annotate(err, "cannot get environ config") |
1898 | + } |
1899 | + h.syslogConfig.Port = cfg.SyslogPort() |
1900 | + rsyslogCACert := cfg.RsyslogCACert() |
1901 | + if rsyslogCACert == nil { |
1902 | + return nil |
1903 | + } |
1904 | + if h.mode == RsyslogModeForwarding { |
1905 | + h.syslogConfig.TLSCACertPath = h.caCertPath() |
1906 | + if err := writeFileAtomic(h.syslogConfig.TLSCACertPath, rsyslogCACert, 0644, 0, 0); err != nil { |
1907 | + return err |
1908 | + } |
1909 | + } |
1910 | + data, err := h.syslogConfig.Render() |
1911 | + if err != nil { |
1912 | + return errgo.Annotate(err, "failed to render rsyslog configuration file") |
1913 | + } |
1914 | + if err := writeFileAtomic(h.syslogConfig.ConfigFilePath(), []byte(data), 0644, 0, 0); err != nil { |
1915 | + return errgo.Annotate(err, "failed to write rsyslog configuration file") |
1916 | + } |
1917 | + logger.Debugf("Reloading rsyslog configuration") |
1918 | + if err := syslog.Restart(); err != nil { |
1919 | + logger.Errorf("failed to reload rsyslog configuration") |
1920 | + return err |
1921 | + } |
1922 | + return nil |
1923 | +} |
1924 | + |
1925 | +func (h *RsyslogConfigHandler) caCertPath() string { |
1926 | + return filepath.Join(h.syslogConfig.LogDir, "ca-cert.pem") |
1927 | +} |
1928 | + |
1929 | +// ensureCertificates ensures that a CA certificate, |
1930 | +// server certificate, and private key exist in the log |
1931 | +// directory, and writes them if not. The CA certificate |
1932 | +// is entered into the environment configuration to be |
1933 | +// picked up by other agents. |
1934 | +func (h *RsyslogConfigHandler) ensureCertificates() error { |
1935 | + // We write ca-cert.pem last, after propagating into state. |
1936 | + // If it's there, then there's nothing to do. Otherwise, |
1937 | + // start over. |
1938 | + caCertPEM := h.caCertPath() |
1939 | + if _, err := os.Stat(caCertPEM); err == nil { |
1940 | + return nil |
1941 | + } |
1942 | + |
1943 | + // Files must be chowned to syslog:adm. |
1944 | + syslogUser, err := user.Lookup("syslog") |
1945 | + if err != nil { |
1946 | + return err |
1947 | + } |
1948 | + syslogUid, err := strconv.Atoi(syslogUser.Uid) |
1949 | + if err != nil { |
1950 | + return err |
1951 | + } |
1952 | + syslogGid, err := strconv.Atoi(syslogUser.Gid) |
1953 | + if err != nil { |
1954 | + return err |
1955 | + } |
1956 | + |
1957 | + // Generate a new CA and server cert/key pairs. |
1958 | + // The CA key will be discarded after the server |
1959 | + // cert has been generated. |
1960 | + expiry := time.Now().UTC().AddDate(10, 0, 0) |
1961 | + caCertPEMBytes, caKeyPEMBytes, err := cert.NewCA("rsyslog", expiry) |
1962 | + if err != nil { |
1963 | + return err |
1964 | + } |
1965 | + rsyslogCertPEMBytes, rsyslogKeyPEMBytes, err := cert.NewServer(caCertPEMBytes, caKeyPEMBytes, expiry, nil) |
1966 | + if err != nil { |
1967 | + return err |
1968 | + } |
1969 | + |
1970 | + // Update the environment config with the CA cert, |
1971 | + // so clients can configure rsyslog. |
1972 | + if err := h.st.SetRsyslogCert(caCertPEMBytes); err != nil { |
1973 | + return err |
1974 | + } |
1975 | + |
1976 | + // Write the certificates and key. The CA certificate must be written last for idempotency. |
1977 | + h.syslogConfig.TLSCACertPath = caCertPEM |
1978 | + h.syslogConfig.TLSCertPath = filepath.Join(h.syslogConfig.LogDir, "rsyslog-cert.pem") |
1979 | + h.syslogConfig.TLSKeyPath = filepath.Join(h.syslogConfig.LogDir, "rsyslog-key.pem") |
1980 | + for _, pair := range []struct { |
1981 | + path string |
1982 | + data []byte |
1983 | + }{ |
1984 | + {h.syslogConfig.TLSCertPath, rsyslogCertPEMBytes}, |
1985 | + {h.syslogConfig.TLSKeyPath, rsyslogKeyPEMBytes}, |
1986 | + {h.syslogConfig.TLSCACertPath, caCertPEMBytes}, |
1987 | + } { |
1988 | + if err := writeFileAtomic(pair.path, pair.data, 0600, syslogUid, syslogGid); err != nil { |
1989 | + return err |
1990 | + } |
1991 | + } |
1992 | + return nil |
1993 | +} |
1994 | + |
1995 | +func writeFileAtomic(path string, data []byte, mode os.FileMode, uid, gid int) error { |
1996 | + temp := path + ".temp" |
1997 | + if err := ioutil.WriteFile(temp, data, mode); err != nil { |
1998 | + return err |
1999 | + } |
2000 | + if uid != -1 { |
2001 | + if err := os.Chown(temp, uid, gid); err != nil { |
2002 | + return err |
2003 | + } |
2004 | + } |
2005 | + return os.Rename(temp, path) |
2006 | +} |
Reviewers: mp+207889_ code.launchpad. net,
Message:
Please take a look.
Description:
Implement rsyslog TLS support
A new config attribute, syslog-tls, is introduced.
This is true for all new environments except for
the local provider, and false (rather, omitted) for
existing environments and any local provider
environments. As with syslog-port, this is immutable.
If syslog-tls is true, then rsyslog-gnutls is
installed and used by the rsyslog configuration that
we generate. The syslog configuration conditionally
uses the TLS transport.
We cannot automatically upgrade existing environments
without additional tooling, as existing server certs
are incompatible with GnuTLS (incorrect Key Usage).
Fixes lp:1281071
https:/ /code.launchpad .net/~axwalk/ juju-core/ lp1281071- rsyslog- tls/+merge/ 207889
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/68070044/
Affected files (+334, -64 lines): cloudinit. go cloudinit/ cloudinit. go cloudinit/ cloudinit_ test.go config/ config. go config/ config_ test.go config. go config_ test.go testing/ syslogconf. go local/environpr ovider. go params/ params. go /deployer/ deployer. go /provisioner/ provisioner. go rsyslogconf. go rsyslogconf_ test.go deployer/ export_ test.go deployer/ simple. go provisioner/ kvm-broker. go provisioner/ lxc-broker. go
A [revision details]
M environs/
M environs/
M environs/
M environs/
M environs/
M log/syslog/
M log/syslog/
M log/syslog/
M provider/
M state/address.go
M state/api/
M state/apiserver
M state/apiserver
M upgrades/
M upgrades/
M worker/
M worker/
M worker/
M worker/