puppet 0.16.0 → 0.18.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CHANGELOG +98 -0
- data/Rakefile +5 -1
- data/bin/puppet +1 -1
- data/bin/puppetca +25 -11
- data/bin/puppetd +189 -66
- data/bin/puppetdoc +79 -62
- data/bin/puppetmasterd +93 -49
- data/bin/puppetrun +385 -0
- data/conf/redhat/client.init +5 -2
- data/conf/redhat/fileserver.conf +1 -1
- data/conf/redhat/lsb-config.patch +51 -0
- data/conf/redhat/puppet.spec +45 -18
- data/conf/redhat/puppetd.conf +32 -4
- data/conf/redhat/server.init +5 -2
- data/conf/solaris/pkginfo +7 -0
- data/conf/solaris/smf/puppetd.xml +77 -0
- data/conf/solaris/smf/puppetmasterd.xml +77 -0
- data/conf/solaris/smf/svc-puppetd +66 -0
- data/conf/solaris/smf/svc-puppetmasterd +62 -0
- data/examples/code/failers/noobjectrvalue +1 -0
- data/examples/code/snippets/deepclassheirarchy.pp +23 -0
- data/examples/code/snippets/defineoverrides.pp +17 -0
- data/examples/code/snippets/emptyexec.pp +3 -0
- data/examples/code/snippets/selectorvalues.pp +6 -1
- data/examples/code/snippets/tagged.pp +35 -0
- data/ext/ldap/puppet.schema +2 -2
- data/install.rb +4 -2
- data/lib/puppet.rb +206 -15
- data/lib/puppet/client.rb +30 -20
- data/lib/puppet/client/ca.rb +2 -2
- data/lib/puppet/client/dipper.rb +5 -9
- data/lib/puppet/client/master.rb +224 -44
- data/lib/puppet/client/pelement.rb +54 -9
- data/lib/puppet/client/proxy.rb +3 -2
- data/lib/puppet/client/reporter.rb +34 -0
- data/lib/puppet/client/runner.rb +17 -0
- data/lib/puppet/config.rb +136 -55
- data/lib/puppet/daemon.rb +59 -37
- data/lib/puppet/element.rb +2 -1
- data/lib/puppet/event.rb +14 -3
- data/lib/puppet/filetype.rb +28 -19
- data/lib/puppet/log.rb +297 -132
- data/lib/puppet/metric.rb +31 -131
- data/lib/puppet/networkclient.rb +73 -46
- data/lib/puppet/parameter.rb +49 -1
- data/lib/puppet/parsedfile.rb +32 -12
- data/lib/puppet/parser/ast.rb +6 -1
- data/lib/puppet/parser/ast/astarray.rb +32 -6
- data/lib/puppet/parser/ast/collection.rb +91 -0
- data/lib/puppet/parser/ast/compdef.rb +2 -2
- data/lib/puppet/parser/ast/component.rb +24 -11
- data/lib/puppet/parser/ast/function.rb +50 -0
- data/lib/puppet/parser/ast/hostclass.rb +70 -22
- data/lib/puppet/parser/ast/node.rb +17 -8
- data/lib/puppet/parser/ast/nodedef.rb +1 -1
- data/lib/puppet/parser/ast/objectdef.rb +28 -10
- data/lib/puppet/parser/ast/selector.rb +4 -1
- data/lib/puppet/parser/functions.rb +145 -0
- data/lib/puppet/parser/interpreter.rb +243 -86
- data/lib/puppet/parser/lexer.rb +5 -4
- data/lib/puppet/parser/parser.rb +586 -505
- data/lib/puppet/parser/scope.rb +337 -187
- data/lib/puppet/rails.rb +115 -0
- data/lib/puppet/rails/database.rb +40 -0
- data/lib/puppet/rails/host.rb +83 -0
- data/lib/puppet/rails/rails_object.rb +42 -0
- data/lib/puppet/rails/rails_parameter.rb +5 -0
- data/lib/puppet/reports/rrdgraph.rb +20 -0
- data/lib/puppet/reports/tagmail.rb +94 -0
- data/lib/puppet/server.rb +20 -4
- data/lib/puppet/server/authconfig.rb +14 -3
- data/lib/puppet/server/authstore.rb +2 -2
- data/lib/puppet/server/ca.rb +23 -11
- data/lib/puppet/server/filebucket.rb +10 -10
- data/lib/puppet/server/fileserver.rb +4 -8
- data/lib/puppet/server/master.rb +19 -22
- data/lib/puppet/server/pelement.rb +28 -16
- data/lib/puppet/server/report.rb +184 -0
- data/lib/puppet/server/runner.rb +62 -0
- data/lib/puppet/server/servlet.rb +23 -9
- data/lib/puppet/sslcertificates/ca.rb +25 -1
- data/lib/puppet/statechange.rb +34 -53
- data/lib/puppet/storage.rb +1 -2
- data/lib/puppet/transaction.rb +305 -133
- data/lib/puppet/transaction/report.rb +42 -0
- data/lib/puppet/transportable.rb +57 -33
- data/lib/puppet/type.rb +260 -127
- data/lib/puppet/type/component.rb +9 -21
- data/lib/puppet/type/cron.rb +367 -116
- data/lib/puppet/type/exec.rb +15 -16
- data/lib/puppet/type/group.rb +9 -1
- data/lib/puppet/type/nameservice.rb +2 -5
- data/lib/puppet/type/nameservice/netinfo.rb +3 -0
- data/lib/puppet/type/nameservice/objectadd.rb +23 -10
- data/lib/puppet/type/nameservice/pw.rb +16 -3
- data/lib/puppet/type/package.rb +25 -75
- data/lib/puppet/type/package/apple.rb +15 -1
- data/lib/puppet/type/package/apt.rb +37 -2
- data/lib/puppet/type/package/blastwave.rb +136 -0
- data/lib/puppet/type/package/dpkg.rb +4 -4
- data/lib/puppet/type/package/gem.rb +119 -0
- data/lib/puppet/type/package/openbsd.rb +7 -6
- data/lib/puppet/type/package/ports.rb +7 -2
- data/lib/puppet/type/package/rpm.rb +1 -1
- data/lib/puppet/type/package/sun.rb +23 -9
- data/lib/puppet/type/package/sunfreeware.rb +7 -0
- data/lib/puppet/type/package/yum.rb +16 -9
- data/lib/puppet/type/parsedtype.rb +7 -5
- data/lib/puppet/type/parsedtype/mount.rb +55 -34
- data/lib/puppet/type/parsedtype/port.rb +7 -1
- data/lib/puppet/type/parsedtype/sshkey.rb +6 -16
- data/lib/puppet/type/pfile.rb +115 -23
- data/lib/puppet/type/pfile/checksum.rb +18 -5
- data/lib/puppet/type/pfile/content.rb +2 -2
- data/lib/puppet/type/pfile/ensure.rb +3 -3
- data/lib/puppet/type/pfile/group.rb +2 -2
- data/lib/puppet/type/pfile/source.rb +28 -17
- data/lib/puppet/type/pfile/target.rb +25 -17
- data/lib/puppet/type/pfilebucket.rb +25 -6
- data/lib/puppet/type/schedule.rb +6 -6
- data/lib/puppet/type/service.rb +24 -14
- data/lib/puppet/type/service/debian.rb +1 -1
- data/lib/puppet/type/service/redhat.rb +13 -10
- data/lib/puppet/type/service/smf.rb +3 -3
- data/lib/puppet/type/state.rb +1 -2
- data/lib/puppet/type/symlink.rb +3 -4
- data/lib/puppet/type/user.rb +22 -10
- data/lib/puppet/type/yumrepo.rb +6 -1
- data/lib/puppet/type/zone.rb +595 -0
- data/lib/puppet/util.rb +58 -12
- data/test/client/client.rb +2 -2
- data/test/client/master.rb +92 -3
- data/test/client/pelement.rb +99 -0
- data/test/executables/puppetbin.rb +3 -4
- data/test/executables/puppetca.rb +3 -3
- data/test/executables/puppetd.rb +3 -3
- data/test/executables/puppetmasterd.rb +1 -5
- data/test/executables/puppetmodule.rb +2 -2
- data/test/language/ast.rb +200 -11
- data/test/language/functions.rb +245 -0
- data/test/language/interpreter.rb +155 -6
- data/test/language/lexer.rb +35 -2
- data/test/language/node.rb +48 -1
- data/test/language/parser.rb +250 -1
- data/test/language/rails.rb +105 -0
- data/test/language/scope.rb +304 -10
- data/test/language/snippets.rb +54 -5
- data/test/language/transportable.rb +60 -28
- data/test/other/config.rb +214 -1
- data/test/other/events.rb +67 -9
- data/test/other/log.rb +31 -5
- data/test/other/metrics.rb +23 -21
- data/test/other/parsedfile.rb +29 -2
- data/test/other/puppet.rb +79 -0
- data/test/other/report.rb +106 -0
- data/test/other/storage.rb +2 -2
- data/test/other/transactions.rb +128 -2
- data/test/puppet/utiltest.rb +10 -5
- data/test/puppettest.rb +193 -21
- data/test/server/authstore.rb +13 -4
- data/test/server/bucket.rb +33 -8
- data/test/server/ca.rb +44 -6
- data/test/server/master.rb +6 -7
- data/test/server/pelement.rb +15 -5
- data/test/server/report.rb +93 -0
- data/test/server/runner.rb +107 -0
- data/test/server/server.rb +28 -1
- data/test/types/cron.rb +339 -31
- data/test/types/file.rb +256 -24
- data/test/types/filebucket.rb +6 -2
- data/test/types/filesources.rb +41 -92
- data/test/types/group.rb +31 -1
- data/test/types/host.rb +2 -1
- data/test/types/mount.rb +18 -1
- data/test/types/package.rb +200 -18
- data/test/types/service.rb +5 -1
- data/test/types/sshkey.rb +2 -1
- data/test/types/symlink.rb +3 -2
- data/test/types/type.rb +180 -1
- data/test/types/user.rb +65 -27
- data/test/types/yumrepo.rb +15 -0
- data/test/types/zone.rb +437 -0
- metadata +43 -4
- data/bin/cf2puppet +0 -186
- data/conf/redhat/puppetmasterd.conf +0 -5
@@ -5,29 +5,32 @@ require 'puppet/type/service/init'
|
|
5
5
|
Puppet.type(:service).newsvctype(:redhat, :init) do
|
6
6
|
# Remove the symlinks
|
7
7
|
def disable
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
begin
|
9
|
+
output = util_execute("/sbin/chkconfig #{self[:name]} off 2>&1")
|
10
|
+
output += util_execute("/sbin/chkconfig --del #{self[:name]} 2>&1")
|
11
|
+
rescue Puppet::ExecutionFailure
|
11
12
|
raise Puppet::Error, "Could not disable %s: %s" %
|
12
13
|
[self.name, output]
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
16
17
|
def enabled?
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
else
|
18
|
+
begin
|
19
|
+
output = util_execute("/sbin/chkconfig #{self[:name]} 2>&1").chomp
|
20
|
+
rescue Puppet::ExecutionFailure
|
21
21
|
return :false
|
22
22
|
end
|
23
|
+
|
24
|
+
return :true
|
23
25
|
end
|
24
26
|
|
25
27
|
# Don't support them specifying runlevels; always use the runlevels
|
26
28
|
# in the init scripts.
|
27
29
|
def enable
|
28
|
-
|
29
|
-
|
30
|
-
|
30
|
+
begin
|
31
|
+
output = util_execute("/sbin/chkconfig --add #{self[:name]} 2>&1")
|
32
|
+
output += util_execute("/sbin/chkconfig #{self[:name]} on 2>&1")
|
33
|
+
rescue Puppet::ExecutionFailure
|
31
34
|
raise Puppet::Error, "Could not enable %s: %s" %
|
32
35
|
[self.name, output]
|
33
36
|
end
|
@@ -45,7 +45,7 @@ Puppet.type(:service).newsvctype(:smf) do
|
|
45
45
|
when "online":
|
46
46
|
#self.warning "matched running %s" % line.inspect
|
47
47
|
return :running
|
48
|
-
when "offline", "disabled"
|
48
|
+
when "offline", "disabled", "uninitialized"
|
49
49
|
#self.warning "matched stopped %s" % line.inspect
|
50
50
|
return :stopped
|
51
51
|
when "legacy_run":
|
@@ -53,7 +53,7 @@ Puppet.type(:service).newsvctype(:smf) do
|
|
53
53
|
"Cannot manage legacy services through SMF"
|
54
54
|
else
|
55
55
|
raise Puppet::Error,
|
56
|
-
"Unmanageable state %s on service %s" %
|
56
|
+
"Unmanageable state '%s' on service %s" %
|
57
57
|
[value, self.name]
|
58
58
|
end
|
59
59
|
end
|
@@ -71,4 +71,4 @@ Puppet.type(:service).newsvctype(:smf) do
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
# $Id: smf.rb
|
74
|
+
# $Id: smf.rb 1375 2006-07-06 17:59:30Z luke $
|
data/lib/puppet/type/state.rb
CHANGED
@@ -109,7 +109,6 @@ class State < Puppet::Parameter
|
|
109
109
|
when :present: (@parent.class.name.to_s + "_created").intern
|
110
110
|
when :absent: (@parent.class.name.to_s + "_removed").intern
|
111
111
|
else
|
112
|
-
warning self.should.inspect
|
113
112
|
(@parent.class.name.to_s + "_changed").intern
|
114
113
|
end
|
115
114
|
|
@@ -391,4 +390,4 @@ class State < Puppet::Parameter
|
|
391
390
|
end
|
392
391
|
end
|
393
392
|
|
394
|
-
# $Id: state.rb
|
393
|
+
# $Id: state.rb 1136 2006-04-26 16:14:47Z luke $
|
data/lib/puppet/type/symlink.rb
CHANGED
@@ -5,7 +5,7 @@ require 'puppet/type/pfile'
|
|
5
5
|
module Puppet
|
6
6
|
newtype(:symlink) do
|
7
7
|
@doc = "Create symbolic links to existing files. **This type is deprecated;
|
8
|
-
use
|
8
|
+
use file instead.**"
|
9
9
|
#newstate(:ensure) do
|
10
10
|
ensurable do
|
11
11
|
require 'etc'
|
@@ -104,7 +104,7 @@ module Puppet
|
|
104
104
|
newparam(:recurse) do
|
105
105
|
desc "If target is a directory, recursively create
|
106
106
|
directories (using `file`'s `source` parameter) and link all
|
107
|
-
contained files. For instance
|
107
|
+
contained files. For instance:
|
108
108
|
|
109
109
|
# The Solaris Blastwave repository installs everything
|
110
110
|
# in /opt/csw; link it into /usr/local
|
@@ -170,7 +170,6 @@ module Puppet
|
|
170
170
|
}
|
171
171
|
|
172
172
|
dir = Puppet.type(:file).implicitcreate(args)
|
173
|
-
dir.parent = @parent
|
174
173
|
@parent.push dir
|
175
174
|
@setparent = true
|
176
175
|
end
|
@@ -184,4 +183,4 @@ module Puppet
|
|
184
183
|
end # Puppet.type(:symlink)
|
185
184
|
end
|
186
185
|
|
187
|
-
# $Id: symlink.rb
|
186
|
+
# $Id: symlink.rb 1300 2006-06-19 19:12:54Z luke $
|
data/lib/puppet/type/user.rb
CHANGED
@@ -246,7 +246,11 @@ module Puppet
|
|
246
246
|
if @parent[:membership] == :inclusive
|
247
247
|
@should.sort.join(",")
|
248
248
|
else
|
249
|
-
|
249
|
+
members = @should
|
250
|
+
if @is.is_a?(Array)
|
251
|
+
members += @is
|
252
|
+
end
|
253
|
+
members.uniq.sort.join(",")
|
250
254
|
end
|
251
255
|
end
|
252
256
|
|
@@ -261,6 +265,9 @@ module Puppet
|
|
261
265
|
unless defined? @is and @is
|
262
266
|
return false
|
263
267
|
end
|
268
|
+
unless @is.class == @should.class
|
269
|
+
return false
|
270
|
+
end
|
264
271
|
return @is.sort == @should.sort
|
265
272
|
end
|
266
273
|
|
@@ -272,16 +279,9 @@ module Puppet
|
|
272
279
|
|
273
280
|
def sync
|
274
281
|
if respond_to? :setgrouplist
|
275
|
-
groups = nil
|
276
|
-
if @parent[:membership] == :inclusive
|
277
|
-
groups = @should
|
278
|
-
else
|
279
|
-
groups = (@is + @should).uniq
|
280
|
-
end
|
281
|
-
|
282
282
|
# Pass them the group list, so that the :membership logic
|
283
283
|
# is all in this class, not in parent classes.
|
284
|
-
setgrouplist(
|
284
|
+
setgrouplist(self.should)
|
285
285
|
return :user_modified
|
286
286
|
else
|
287
287
|
super
|
@@ -331,6 +331,14 @@ module Puppet
|
|
331
331
|
defaultto :minimum
|
332
332
|
end
|
333
333
|
|
334
|
+
newparam(:allowdupe) do
|
335
|
+
desc "Whether to allow duplicate UIDs."
|
336
|
+
|
337
|
+
newvalues(:true, :false)
|
338
|
+
|
339
|
+
defaultto false
|
340
|
+
end
|
341
|
+
|
334
342
|
@doc = "Manage users. Currently can create and modify users, but
|
335
343
|
cannot delete them. Theoretically all of the parameters are
|
336
344
|
optional, but if no parameters are specified the comment will
|
@@ -376,6 +384,10 @@ module Puppet
|
|
376
384
|
}
|
377
385
|
end
|
378
386
|
|
387
|
+
if @states.include?(:groups) and groups = @states[:groups].should.split(",")
|
388
|
+
autos += groups
|
389
|
+
end
|
390
|
+
|
379
391
|
autos
|
380
392
|
end
|
381
393
|
|
@@ -441,4 +453,4 @@ module Puppet
|
|
441
453
|
end
|
442
454
|
end
|
443
455
|
|
444
|
-
# $Id: user.rb
|
456
|
+
# $Id: user.rb 1416 2006-07-21 19:05:30Z luke $
|
data/lib/puppet/type/yumrepo.rb
CHANGED
@@ -22,7 +22,11 @@ module Puppet
|
|
22
22
|
result = nil
|
23
23
|
else
|
24
24
|
result = set
|
25
|
-
|
25
|
+
if should == :absent
|
26
|
+
parent.section[inikey] = nil
|
27
|
+
else
|
28
|
+
parent.section[inikey] = should
|
29
|
+
end
|
26
30
|
end
|
27
31
|
return result
|
28
32
|
end
|
@@ -163,6 +167,7 @@ module Puppet
|
|
163
167
|
@inifile = nil
|
164
168
|
@yumconf = "/etc/yum.conf"
|
165
169
|
@defaultrepodir = nil
|
170
|
+
super
|
166
171
|
end
|
167
172
|
|
168
173
|
# Return the Puppet::IniConfig::Section for this yumrepo element
|
@@ -0,0 +1,595 @@
|
|
1
|
+
Puppet::Type.newtype(:zone) do
|
2
|
+
@doc = "Solaris zones."
|
3
|
+
|
4
|
+
# These states modify the zone configuration, and they need to provide
|
5
|
+
# the text separately from syncing it, so all config statements can be rolled
|
6
|
+
# into a single creation statement.
|
7
|
+
class ZoneConfigState < Puppet::State
|
8
|
+
# Perform the config operation.
|
9
|
+
def sync
|
10
|
+
@parent.cfg self.configtext
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Those states that can have multiple instances.
|
15
|
+
class ZoneMultiConfigState < ZoneConfigState
|
16
|
+
def configtext
|
17
|
+
list = @should
|
18
|
+
|
19
|
+
unless @is.is_a? Symbol
|
20
|
+
if @is.is_a? Array
|
21
|
+
list += @is
|
22
|
+
else
|
23
|
+
if @is
|
24
|
+
list << @is
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Some hackery so we can test whether @is is an array or a symbol
|
30
|
+
if @is.is_a? Array
|
31
|
+
tmpis = @is
|
32
|
+
else
|
33
|
+
if @is
|
34
|
+
tmpis = [@is]
|
35
|
+
else
|
36
|
+
tmpis = []
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
rms = []
|
41
|
+
adds = []
|
42
|
+
# Collect the modifications to make
|
43
|
+
list.sort.uniq.collect do |obj|
|
44
|
+
# Skip objectories that are configured and should be
|
45
|
+
next if tmpis.include?(obj) and @should.include?(obj)
|
46
|
+
|
47
|
+
if tmpis.include?(obj)
|
48
|
+
rms << obj
|
49
|
+
else
|
50
|
+
adds << obj
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# And then perform all of the removals before any of the adds.
|
55
|
+
(rms.collect { |o| rm(o) } + adds.collect { |o| add(o) }).join("\n")
|
56
|
+
end
|
57
|
+
|
58
|
+
# We want all specified directories to be included.
|
59
|
+
def insync?
|
60
|
+
if @is.is_a? Array and @should.is_a? Array
|
61
|
+
@is.sort == @should.sort
|
62
|
+
else
|
63
|
+
@is == @should
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
ensurable do
|
69
|
+
desc "The running state of the zone. The valid states directly reflect
|
70
|
+
the states that ``zoneadm`` provides. The states are linear,
|
71
|
+
in that a zone must be ``configured`` then ``installed``, and
|
72
|
+
only then can be ``running``. Note also that ``halt`` is currently
|
73
|
+
used to stop zones."
|
74
|
+
|
75
|
+
@states = {}
|
76
|
+
|
77
|
+
def self.newvalue(name, hash)
|
78
|
+
if @parametervalues.is_a? Hash
|
79
|
+
@parametervalues = []
|
80
|
+
end
|
81
|
+
|
82
|
+
@parametervalues << name
|
83
|
+
|
84
|
+
@states[name] = hash
|
85
|
+
hash[:name] = name
|
86
|
+
end
|
87
|
+
|
88
|
+
newvalue :absent, :down => :destroy
|
89
|
+
newvalue :configured, :up => :configure, :down => :uninstall
|
90
|
+
newvalue :installed, :up => :install, :down => :stop
|
91
|
+
newvalue :running, :up => :start
|
92
|
+
|
93
|
+
defaultto :running
|
94
|
+
|
95
|
+
def self.valueindex(value)
|
96
|
+
@parametervalues.index(value)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Return all of the states between two listed values, exclusive
|
100
|
+
# of the first item.
|
101
|
+
def self.valueslice(first, second)
|
102
|
+
findex = sindex = nil
|
103
|
+
unless findex = @parametervalues.index(first)
|
104
|
+
raise ArgumentError, "'%s' is not a valid zone state" % first
|
105
|
+
end
|
106
|
+
unless sindex = @parametervalues.index(second)
|
107
|
+
raise ArgumentError, "'%s' is not a valid zone state" % first
|
108
|
+
end
|
109
|
+
list = nil
|
110
|
+
|
111
|
+
# Apparently ranges are unidirectional, so we have to reverse
|
112
|
+
# the range op twice.
|
113
|
+
if findex > sindex
|
114
|
+
list = @parametervalues[sindex..findex].collect do |name|
|
115
|
+
@states[name]
|
116
|
+
end.reverse
|
117
|
+
else
|
118
|
+
list = @parametervalues[findex..sindex].collect do |name|
|
119
|
+
@states[name]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# The first result is the current state, so don't return it.
|
124
|
+
list[1..-1]
|
125
|
+
end
|
126
|
+
|
127
|
+
def is=(value)
|
128
|
+
value = value.intern if value.is_a? String
|
129
|
+
@is = value
|
130
|
+
end
|
131
|
+
|
132
|
+
def sync
|
133
|
+
method = nil
|
134
|
+
if up?
|
135
|
+
dir = :up
|
136
|
+
else
|
137
|
+
dir = :down
|
138
|
+
end
|
139
|
+
|
140
|
+
# We need to get the state we're currently in and just call
|
141
|
+
# everything between it and us.
|
142
|
+
states = self.class.valueslice(self.is, self.should)
|
143
|
+
|
144
|
+
states.each do |st|
|
145
|
+
if method = st[dir]
|
146
|
+
warned = false
|
147
|
+
while @parent.processing?
|
148
|
+
unless warned
|
149
|
+
info "Waiting for zone to finish processing"
|
150
|
+
warned = true
|
151
|
+
end
|
152
|
+
sleep 1
|
153
|
+
end
|
154
|
+
@parent.send(method)
|
155
|
+
else
|
156
|
+
raise Puppet::DevError, "Cannot move %s from %s" %
|
157
|
+
[dir, st[:name]]
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
return ("zone_" + self.should.to_s).intern
|
162
|
+
end
|
163
|
+
|
164
|
+
# Are we moving up the state tree?
|
165
|
+
def up?
|
166
|
+
self.class.valueindex(self.is) < self.class.valueindex(self.should)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
newparam(:name) do
|
171
|
+
desc "The name of the zone."
|
172
|
+
|
173
|
+
isnamevar
|
174
|
+
end
|
175
|
+
|
176
|
+
newparam(:id) do
|
177
|
+
desc "The numerical ID of the zone. This number is autogenerated
|
178
|
+
and cannot be changed."
|
179
|
+
end
|
180
|
+
|
181
|
+
newstate(:ip, ZoneMultiConfigState) do
|
182
|
+
require 'ipaddr'
|
183
|
+
|
184
|
+
desc "The IP address of the zone. IP addresses must be specified
|
185
|
+
with the interface, separated by a colon, e.g.: bge0:192.168.0.1.
|
186
|
+
For multiple interfaces, specify them in an array."
|
187
|
+
|
188
|
+
validate do |value|
|
189
|
+
unless value =~ /:/
|
190
|
+
raise ArgumentError,
|
191
|
+
"IP addresses must specify the interface and the address, separated by a colon."
|
192
|
+
end
|
193
|
+
|
194
|
+
interface, address = value.split(':')
|
195
|
+
|
196
|
+
begin
|
197
|
+
IPAddr.new(address)
|
198
|
+
rescue ArgumentError
|
199
|
+
raise ArgumentError, "'%s' is an invalid IP address" % address
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# Add a directory to our list of inherited directories.
|
204
|
+
def add(str)
|
205
|
+
interface, ip = ipsplit(str)
|
206
|
+
"add net
|
207
|
+
set address=#{ip}
|
208
|
+
set physical=#{interface}
|
209
|
+
end
|
210
|
+
"
|
211
|
+
end
|
212
|
+
|
213
|
+
# Convert a string into the component interface and address
|
214
|
+
def ipsplit(str)
|
215
|
+
interface, address = str.split(':')
|
216
|
+
return interface, address
|
217
|
+
end
|
218
|
+
|
219
|
+
def rm(str)
|
220
|
+
interface, ip = ipsplit(str)
|
221
|
+
# Reality seems to disagree with the documentation here; the docs
|
222
|
+
# specify that braces are required, but they're apparently only
|
223
|
+
# required if you're specifying multiple values.
|
224
|
+
"remove net address=#{ip}"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
newstate(:autoboot, ZoneConfigState) do
|
229
|
+
desc "Whether the zone should automatically boot."
|
230
|
+
|
231
|
+
defaultto true
|
232
|
+
|
233
|
+
newvalue(:true) {}
|
234
|
+
newvalue(:false) {}
|
235
|
+
|
236
|
+
def configtext
|
237
|
+
"set autoboot=#{self.should}"
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
newstate(:pool, ZoneConfigState) do
|
242
|
+
desc "The resource pool for this zone."
|
243
|
+
|
244
|
+
def configtext
|
245
|
+
"set pool=#{self.should}"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
newstate(:inherit, ZoneMultiConfigState) do
|
250
|
+
desc "The list of directories that the zone inherits from the global
|
251
|
+
zone. All directories must be fully qualified."
|
252
|
+
|
253
|
+
validate do |value|
|
254
|
+
unless value =~ /^\//
|
255
|
+
raise ArgumentError, "The zone base must be fully qualified"
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
# Add a directory to our list of inherited directories.
|
260
|
+
def add(dir)
|
261
|
+
"add inherit-pkg-dir\nset dir=#{dir}\nend"
|
262
|
+
end
|
263
|
+
|
264
|
+
def rm(dir)
|
265
|
+
# Reality seems to disagree with the documentation here; the docs
|
266
|
+
# specify that braces are required, but they're apparently only
|
267
|
+
# required if you're specifying multiple values.
|
268
|
+
"remove inherit-pkg-dir dir=#{dir}"
|
269
|
+
end
|
270
|
+
|
271
|
+
def should
|
272
|
+
@should
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
# Specify the sysidcfg file. This is pretty hackish, because it's
|
277
|
+
# only used to boot the zone the very first time.
|
278
|
+
newparam(:sysidcfg) do
|
279
|
+
desc %{The text to go into the sysidcfg file when the zone is first
|
280
|
+
booted. The best way is to use a template:
|
281
|
+
|
282
|
+
# $templatedir/sysidcfg
|
283
|
+
system_locale=en_US
|
284
|
+
timezone=GMT
|
285
|
+
terminal=xterms
|
286
|
+
security_policy=NONE
|
287
|
+
root_password=<%= password %>
|
288
|
+
timeserver=localhost
|
289
|
+
name_service=DNS {domain_name=<%= domain %>
|
290
|
+
name_server=<%= nameserver %>}
|
291
|
+
network_interface=primary {hostname=<%= name %>
|
292
|
+
ip_address=<%= ip %>
|
293
|
+
netmask=<%= netmask %>
|
294
|
+
protocol_ipv6=no
|
295
|
+
default_route=<%= defaultroute %>}
|
296
|
+
nfs4_domain=dynamic
|
297
|
+
|
298
|
+
And then call that:
|
299
|
+
|
300
|
+
zone { myzone:
|
301
|
+
ip => "bge0:192.168.0.23",
|
302
|
+
sysidcfg => template(sysidcfg),
|
303
|
+
path => "/opt/zones/myzone"
|
304
|
+
}
|
305
|
+
|
306
|
+
The sysidcfg only matters on the first booting of the zone,
|
307
|
+
so Puppet only checks for it at that time.
|
308
|
+
}
|
309
|
+
end
|
310
|
+
|
311
|
+
newparam(:path) do
|
312
|
+
desc "The root of the zone's filesystem. Must be a fully qualified
|
313
|
+
file name. If you include '%s' in the path, then it will be
|
314
|
+
replaced with the zone's name. At this point, you cannot use
|
315
|
+
Puppet to move a zone."
|
316
|
+
|
317
|
+
validate do |value|
|
318
|
+
unless value =~ /^\//
|
319
|
+
raise ArgumentError, "The zone base must be fully qualified"
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
munge do |value|
|
324
|
+
if value =~ /%s/
|
325
|
+
value % @parent[:name]
|
326
|
+
else
|
327
|
+
value
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
# If Puppet is also managing the base dir or its parent dir, list them
|
333
|
+
# both as prerequisites.
|
334
|
+
autorequire(:file) do
|
335
|
+
if @parameters.include? :path
|
336
|
+
[@parameters[:path].value, File.dirname(@parameters[:path].value)]
|
337
|
+
else
|
338
|
+
nil
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
# Convert the output of a list into a hash
|
343
|
+
def self.line2hash(line)
|
344
|
+
fields = [:id, :name, :ensure, :path]
|
345
|
+
|
346
|
+
hash = {}
|
347
|
+
line.split(":").each_with_index { |value, index|
|
348
|
+
hash[fields[index]] = value
|
349
|
+
}
|
350
|
+
|
351
|
+
# Configured but not installed zones do not have IDs
|
352
|
+
if hash[:id] == "-"
|
353
|
+
hash.delete(:id)
|
354
|
+
end
|
355
|
+
|
356
|
+
return hash
|
357
|
+
end
|
358
|
+
|
359
|
+
def self.list
|
360
|
+
%x{/usr/sbin/zoneadm list -cp}.split("\n").collect do |line|
|
361
|
+
hash = line2hash(line)
|
362
|
+
|
363
|
+
obj = nil
|
364
|
+
unless obj = @objects[hash[:name]]
|
365
|
+
obj = create(:name => hash[:name])
|
366
|
+
end
|
367
|
+
|
368
|
+
obj.setstatus(hash)
|
369
|
+
|
370
|
+
obj
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
# Execute a configuration string. Can't be private because it's called
|
375
|
+
# by the states.
|
376
|
+
def cfg(str)
|
377
|
+
debug "Executing '%s' in zone %s" % [str, self[:name]]
|
378
|
+
IO.popen("/usr/sbin/zonecfg -z %s -f - 2>&1" % self[:name], "w") do |pipe|
|
379
|
+
pipe.puts str
|
380
|
+
end
|
381
|
+
|
382
|
+
unless $? == 0
|
383
|
+
raise ArgumentError, "Failed to apply configuration"
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
# Perform all of our configuration steps.
|
388
|
+
def configure
|
389
|
+
# If the thing is entirely absent, then we need to create the config.
|
390
|
+
str = %{create -b
|
391
|
+
set zonepath=%s
|
392
|
+
} % self[:path]
|
393
|
+
|
394
|
+
# Then perform all of our configuration steps.
|
395
|
+
@states.each do |name, state|
|
396
|
+
if state.is_a? ZoneConfigState and ! state.insync?
|
397
|
+
str += state.configtext + "\n"
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
str += "commit\n"
|
402
|
+
cfg(str)
|
403
|
+
end
|
404
|
+
|
405
|
+
def destroy
|
406
|
+
begin
|
407
|
+
execute("/usr/sbin/zonecfg -z #{self[:name]} delete -F")
|
408
|
+
rescue Puppet::ExecutionFailure => detail
|
409
|
+
self.fail "Could not destroy zone: %s" % detail
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
def install
|
414
|
+
begin
|
415
|
+
execute("/usr/sbin/zoneadm -z #{self[:name]} install")
|
416
|
+
rescue Puppet::ExecutionFailure => detail
|
417
|
+
self.fail "Could not install zone: %s" % detail
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
# We need a way to test whether a zone is in process. Our 'ensure'
|
422
|
+
# state models the static states, but we need to handle the temporary ones.
|
423
|
+
def processing?
|
424
|
+
if hash = statushash()
|
425
|
+
case hash[:ensure]
|
426
|
+
when "incomplete", "ready", "shutting_down"
|
427
|
+
true
|
428
|
+
else
|
429
|
+
false
|
430
|
+
end
|
431
|
+
else
|
432
|
+
false
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
def retrieve
|
437
|
+
if hash = statushash()
|
438
|
+
setstatus(hash)
|
439
|
+
|
440
|
+
# Now retrieve the configuration itself and set appropriately.
|
441
|
+
getconfig()
|
442
|
+
else
|
443
|
+
@states.each do |name, state|
|
444
|
+
state.is = :absent
|
445
|
+
end
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
# Take the results of a listing and set everything appropriately.
|
450
|
+
def setstatus(hash)
|
451
|
+
hash.each do |param, value|
|
452
|
+
next if param == :name
|
453
|
+
case self.class.attrtype(param)
|
454
|
+
when :state:
|
455
|
+
self.is = [param, value]
|
456
|
+
else
|
457
|
+
self[param] = value
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
# For any configured items that are not found, mark absent.
|
462
|
+
@states.each do |name, st|
|
463
|
+
next unless st.is_a? ZoneConfigState
|
464
|
+
|
465
|
+
unless hash.has_key? st.name
|
466
|
+
st.is = :absent
|
467
|
+
end
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
def start
|
472
|
+
# Check the sysidcfg stuff
|
473
|
+
if cfg = self[:sysidcfg]
|
474
|
+
path = File.join(self[:path], "root", "etc", "sysidcfg")
|
475
|
+
|
476
|
+
unless File.exists?(path)
|
477
|
+
begin
|
478
|
+
File.open(path, "w", 0600) do |f|
|
479
|
+
f.puts cfg
|
480
|
+
end
|
481
|
+
rescue => detail
|
482
|
+
if Puppet[:debug]
|
483
|
+
puts detail.stacktrace
|
484
|
+
end
|
485
|
+
raise Puppet::Error, "Could not create sysidcfg: %s" % detail
|
486
|
+
end
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
begin
|
491
|
+
execute("/usr/sbin/zoneadm -z #{self[:name]} boot")
|
492
|
+
rescue Puppet::ExecutionFailure => detail
|
493
|
+
self.fail "Could not start zone: %s" % detail
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
def stop
|
498
|
+
begin
|
499
|
+
execute("/usr/sbin/zoneadm -z #{self[:name]} halt")
|
500
|
+
rescue Puppet::ExecutionFailure => detail
|
501
|
+
self.fail "Could not halt zone: %s" % detail
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
def unconfigure
|
506
|
+
begin
|
507
|
+
execute("/usr/sbin/zonecfg -z #{self[:name]} delete -F")
|
508
|
+
rescue Puppet::ExecutionFailure => detail
|
509
|
+
self.fail "Could not unconfigure zone: %s" % detail
|
510
|
+
end
|
511
|
+
end
|
512
|
+
|
513
|
+
def uninstall
|
514
|
+
begin
|
515
|
+
execute("/usr/sbin/zoneadm -z #{self[:name]} uninstall -F")
|
516
|
+
rescue Puppet::ExecutionFailure => detail
|
517
|
+
self.fail "Could not halt zone: %s" % detail
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
private
|
522
|
+
|
523
|
+
# Turn the results of getconfig into status information.
|
524
|
+
def config2status(config)
|
525
|
+
config.each do |name, value|
|
526
|
+
case name
|
527
|
+
when :autoboot:
|
528
|
+
self.is = [:autoboot, value.intern]
|
529
|
+
when :zonepath:
|
530
|
+
# Nothing; this is set in the zoneadm list command
|
531
|
+
when :pool:
|
532
|
+
self.is = [:pool, value]
|
533
|
+
when "inherit-pkg-dir":
|
534
|
+
dirs = value.collect do |hash|
|
535
|
+
hash[:dir]
|
536
|
+
end
|
537
|
+
|
538
|
+
self.is = [:inherit, dirs]
|
539
|
+
when "net":
|
540
|
+
vals = value.collect do |hash|
|
541
|
+
"%s:%s" % [hash[:physical], hash[:address]]
|
542
|
+
end
|
543
|
+
self.is = [:ip, vals]
|
544
|
+
end
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
# Collect the configuration of the zone.
|
549
|
+
def getconfig
|
550
|
+
output = execute("/usr/sbin/zonecfg -z %s info" % self[:name])
|
551
|
+
|
552
|
+
name = nil
|
553
|
+
current = nil
|
554
|
+
hash = {}
|
555
|
+
output.split("\n").each do |line|
|
556
|
+
case line
|
557
|
+
when /^(\S+):\s*$/:
|
558
|
+
name = $1
|
559
|
+
current = nil # reset it
|
560
|
+
when /^(\S+):\s*(.+)$/:
|
561
|
+
hash[$1.intern] = $2
|
562
|
+
#self.is = [$1.intern, $2]
|
563
|
+
when /^\s+(\S+):\s*(.+)$/:
|
564
|
+
if name
|
565
|
+
unless hash.include? name
|
566
|
+
hash[name] = []
|
567
|
+
end
|
568
|
+
|
569
|
+
unless current
|
570
|
+
current = {}
|
571
|
+
hash[name] << current
|
572
|
+
end
|
573
|
+
current[$1.intern] = $2
|
574
|
+
else
|
575
|
+
err "Ignoring '%s'" % line
|
576
|
+
end
|
577
|
+
else
|
578
|
+
debug "Ignoring zone output '%s'" % line
|
579
|
+
end
|
580
|
+
end
|
581
|
+
config2status(hash)
|
582
|
+
end
|
583
|
+
|
584
|
+
def statushash
|
585
|
+
begin
|
586
|
+
output = execute("/usr/sbin/zoneadm -z #{self[:name]} list -p 2>/dev/null")
|
587
|
+
rescue Puppet::ExecutionFailure => detail
|
588
|
+
return nil
|
589
|
+
end
|
590
|
+
|
591
|
+
return self.class.line2hash(output.chomp)
|
592
|
+
end
|
593
|
+
end
|
594
|
+
|
595
|
+
# $Id: zone.rb 1386 2006-07-11 18:38:42Z luke $
|