1 Enhance the zone provider to configure zones using a zonecfg export file format. |
|
2 Enhance the output of puppet resource zone, and fix zone clone functionality. |
|
3 --- puppet-3.4.1/lib/puppet/provider/zone/solaris.rb.orig 2013-07-29 15:48:58.118553584 -0600 |
|
4 +++ puppet-3.4.1/lib/puppet/provider/zone/solaris.rb 2013-07-29 15:49:21.053204412 -0600 |
|
5 @@ -1,5 +1,5 @@ |
|
6 Puppet::Type.type(:zone).provide(:solaris) do |
|
7 - desc "Provider for Solaris Zones." |
|
8 + desc "Provider for Solaris zones." |
|
9 |
|
10 commands :adm => "/usr/sbin/zoneadm", :cfg => "/usr/sbin/zonecfg" |
|
11 defaultfor :osfamily => :solaris |
|
12 @@ -8,20 +8,20 @@ |
|
13 |
|
14 # Convert the output of a list into a hash |
|
15 def self.line2hash(line) |
|
16 - fields = [:id, :name, :ensure, :path, :uuid, :brand, :iptype] |
|
17 + fields = [:id, :name, :ensure, :zonepath, :uuid, :brand, :iptype ] |
|
18 properties = Hash[fields.zip(line.split(':'))] |
|
19 |
|
20 - del_id = [:brand, :uuid] |
|
21 + del_id = [:id, :uuid] |
|
22 + |
|
23 # Configured but not installed zones do not have IDs |
|
24 del_id << :id if properties[:id] == "-" |
|
25 del_id.each { |p| properties.delete(p) } |
|
26 - |
|
27 properties[:ensure] = properties[:ensure].intern |
|
28 - properties[:iptype] = 'exclusive' if properties[:iptype] == 'excl' |
|
29 |
|
30 properties |
|
31 end |
|
32 |
|
33 + |
|
34 def self.instances |
|
35 # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com] |
|
36 x = adm(:list, "-cp").split("\n").collect do |line| |
|
37 @@ -29,109 +29,64 @@ |
|
38 end |
|
39 end |
|
40 |
|
41 - def multi_conf(name, should, &action) |
|
42 - has = properties[name] |
|
43 - has = [] if has == :absent |
|
44 - rms = has - should |
|
45 - adds = should - has |
|
46 - (rms.map{|o| action.call(:rm,o)} + adds.map{|o| action.call(:add,o)}).join("\n") |
|
47 - end |
|
48 - |
|
49 - def self.def_prop(var, str) |
|
50 - define_method('%s_conf' % var.to_s) do |v| |
|
51 - str % v |
|
52 - end |
|
53 - define_method('%s=' % var.to_s) do |v| |
|
54 - setconfig self.send( ('%s_conf'% var).intern, v) |
|
55 - end |
|
56 - end |
|
57 + |
|
58 + # Read in the zone configuration parameters and properties and |
|
59 + # perform the zone configuration. Options are cloning the zone, |
|
60 + # which needs a zonecfg_export file, configuring an archive, which |
|
61 + # takes optional zonecfg_export and archived_zonename parameters, |
|
62 + # or performing a zone configuration, which requires a zonecfg_export |
|
63 + # file or string. |
|
64 + def configure |
|
65 |
|
66 - def self.def_multiprop(var, &conf) |
|
67 - define_method(var.to_s) do |v| |
|
68 - o = properties[var] |
|
69 - return '' if o.nil? or o == :absent |
|
70 - o.join(' ') |
|
71 - end |
|
72 - define_method('%s=' % var.to_s) do |v| |
|
73 - setconfig self.send( ('%s_conf'% var).intern, v) |
|
74 - end |
|
75 - define_method('%s_conf' % var.to_s) do |v| |
|
76 - multi_conf(var, v, &conf) |
|
77 + if @resource[:archive].nil? && @resource[:zonecfg_export].nil? |
|
78 + raise Puppet::Error, "No configuration resource is defined." |
|
79 end |
|
80 - end |
|
81 |
|
82 - def_prop :iptype, "set ip-type=%s" |
|
83 - def_prop :autoboot, "set autoboot=%s" |
|
84 - def_prop :path, "set zonepath=%s" |
|
85 - def_prop :pool, "set pool=%s" |
|
86 - def_prop :shares, "add rctl\nset name=zone.cpu-shares\nadd value (priv=privileged,limit=%s,action=none)\nend" |
|
87 - |
|
88 - def_multiprop :ip do |action, str| |
|
89 - interface, ip, defrouter = str.split(':') |
|
90 - case action |
|
91 - when :add |
|
92 - cmd = ["add net"] |
|
93 - cmd << "set physical=#{interface}" if interface |
|
94 - cmd << "set address=#{ip}" if ip |
|
95 - cmd << "set defrouter=#{defrouter}" if defrouter |
|
96 - cmd << "end" |
|
97 - cmd.join("\n") |
|
98 - when :rm |
|
99 - if ip |
|
100 - "remove net address=#{ip}" |
|
101 - elsif interface |
|
102 - "remove net physical=#{interface}" |
|
103 - else |
|
104 - raise ArgumentError, "can not remove network based on default router" |
|
105 + command = String.new |
|
106 + if @resource[:clone] |
|
107 + if !@resource[:zonecfg_export] |
|
108 + raise Puppet::Error, "A zone configuration must be defined to |
|
109 + clone a zone." |
|
110 + end |
|
111 + command = "#{command(:cfg)} -z #{@resource[:name]} -f #{@resource[:zonecfg_export]}" |
|
112 + else |
|
113 + unless @resource[:zonecfg_export].nil? || @resource[:zonecfg_export].empty? |
|
114 + begin |
|
115 + file = File.open(@resource[:zonecfg_export], "rb") |
|
116 + str = file.read.gsub(/[\n]\n*\s*/, "; ") |
|
117 + rescue |
|
118 + str = @resource[:zonecfg_export].gsub(/[\n]\n*\s*/, "; ") |
|
119 + ensure |
|
120 + file.close unless file.nil? |
|
121 + end |
|
122 + @property_hash.clear |
|
123 end |
|
124 - else self.fail action |
|
125 - end |
|
126 - end |
|
127 |
|
128 - def_multiprop :dataset do |action, str| |
|
129 - case action |
|
130 - when :add; ['add dataset',"set name=#{str}",'end'].join("\n") |
|
131 - when :rm; "remove dataset name=#{str}" |
|
132 - else self.fail action |
|
133 - end |
|
134 - end |
|
135 + unless @resource[:archive].nil? || @resource[:archive].empty? |
|
136 + if !str.nil? |
|
137 + command = "#{command(:cfg)} -z #{@resource[:name]} \'create -a #{@resource[:archive]};#{str}\'" |
|
138 + else |
|
139 + command = "#{command(:cfg)} -z #{@resource[:name]} create -a #{@resource[:archive]} " |
|
140 + end |
|
141 + if @resource[:archived_zonename] |
|
142 + command << " -z #{@resource[:archived_zonename]}" |
|
143 + end |
|
144 + end |
|
145 |
|
146 - def_multiprop :inherit do |action, str| |
|
147 - case action |
|
148 - when :add; ['add inherit-pkg-dir', "set dir=#{str}",'end'].join("\n") |
|
149 - when :rm; "remove inherit-pkg-dir dir=#{str}" |
|
150 - else self.fail action |
|
151 + if !@resource[:zonecfg_export].nil? && @resource[:archive].nil? |
|
152 + command = "#{command(:cfg)} -z #{@resource[:name]} \'#{str}\'" |
|
153 + end |
|
154 end |
|
155 - end |
|
156 |
|
157 - def my_properties |
|
158 - [:path, :iptype, :autoboot, :pool, :shares, :ip, :dataset, :inherit] |
|
159 - end |
|
160 - |
|
161 - # Perform all of our configuration steps. |
|
162 - def configure |
|
163 - self.fail "Path is required" unless @resource[:path] |
|
164 - arr = ["create -b #{@resource[:create_args]}"] |
|
165 - |
|
166 - # Then perform all of our configuration steps. It's annoying |
|
167 - # that we need this much internal info on the resource. |
|
168 - self.resource.properties.each do |property| |
|
169 - next unless my_properties.include? property.name |
|
170 - method = (property.name.to_s + '_conf').intern |
|
171 - arr << self.send(method ,@resource[property.name]) unless property.safe_insync?(properties[property.name]) |
|
172 + if command |
|
173 + r = exec_cmd(:cmd => command) |
|
174 end |
|
175 - setconfig(arr.join("\n")) |
|
176 end |
|
177 |
|
178 def destroy |
|
179 zonecfg :delete, "-F" |
|
180 end |
|
181 |
|
182 - def add_cmd(cmd) |
|
183 - @cmds = [] if @cmds.nil? |
|
184 - @cmds << cmd |
|
185 - end |
|
186 - |
|
187 def exists? |
|
188 properties[:ensure] != :absent |
|
189 end |
|
190 @@ -139,31 +94,31 @@ |
|
191 # We cannot use the execpipe in util because the pipe is not opened in |
|
192 # read/write mode. |
|
193 def exec_cmd(var) |
|
194 - # In bash, the exit value of the last command is the exit value of the |
|
195 - # entire pipeline |
|
196 - out = execute("echo \"#{var[:input]}\" | #{var[:cmd]}", :failonfail => false, :combine => true) |
|
197 - st = $?.exitstatus |
|
198 - {:out => out, :exit => st} |
|
199 - end |
|
200 - |
|
201 - # Clear out the cached values. |
|
202 - def flush |
|
203 - return if @cmds.nil? || @cmds.empty? |
|
204 - str = (@cmds << "commit" << "exit").join("\n") |
|
205 - @cmds = [] |
|
206 - @property_hash.clear |
|
207 - |
|
208 - command = "#{command(:cfg)} -z #{@resource[:name]} -f -" |
|
209 - r = exec_cmd(:cmd => command, :input => str) |
|
210 - if r[:exit] != 0 or r[:out] =~ /not allowed/ |
|
211 - raise ArgumentError, "Failed to apply configuration" |
|
212 + if var[:input] |
|
213 + execute("echo \"#{var[:input]}\" | #{var[:cmd]}", :failonfail => true, :combine => true) |
|
214 + else |
|
215 + execute("#{var[:cmd]}", :failonfail => true, :combine => true) |
|
216 end |
|
217 end |
|
218 |
|
219 + |
|
220 def install(dummy_argument=:work_arround_for_ruby_GC_bug) |
|
221 + if ['5.11', '5.12'].include? Facter.value(:kernelrelease) |
|
222 + if !@resource[:install_args] and @resource[:config_profile] |
|
223 + @resource[:install_args] = " -c " + @resource[:config_profile] |
|
224 + elsif !@resource[:install_args] and @resource[:archive] |
|
225 + @resource[:install_args] = " -a " + @resource[:archive] |
|
226 + if @resource[:archived_zonename] |
|
227 + @resource[:install_args] << " -z " + @resource[:archived_zonename] |
|
228 + end |
|
229 + elsif @resource[:config_profile] |
|
230 + @resource[:install_args] << " -c " + @resource[:config_profile] |
|
231 + end |
|
232 + end |
|
233 + |
|
234 if @resource[:clone] # TODO: add support for "-s snapshot" |
|
235 - zoneadm :clone, @resource[:clone] |
|
236 - elsif @resource[:install_args] |
|
237 + zoneadm :clone, @resource[:clone] |
|
238 + elsif @resource[:install_args] |
|
239 zoneadm :install, @resource[:install_args].split(" ") |
|
240 else |
|
241 zoneadm :install |
|
242 @@ -183,11 +138,12 @@ |
|
243 end |
|
244 end |
|
245 @property_hash.dup |
|
246 + |
|
247 end |
|
248 |
|
249 # We need a way to test whether a zone is in process. Our 'ensure' |
|
250 # property models the static states, but we need to handle the temporary ones. |
|
251 - def processing? |
|
252 + def processing? |
|
253 hash = status |
|
254 return false unless hash |
|
255 ["incomplete", "ready", "shutting_down"].include? hash[:ensure] |
|
256 @@ -215,7 +171,6 @@ |
|
257 # |
|
258 def getconfig |
|
259 output = zonecfg :info |
|
260 - |
|
261 name = nil |
|
262 current = nil |
|
263 hash = {} |
|
264 @@ -245,14 +200,9 @@ |
|
265 hash |
|
266 end |
|
267 |
|
268 - # Execute a configuration string. Can't be private because it's called |
|
269 - # by the properties. |
|
270 - def setconfig(str) |
|
271 - add_cmd str |
|
272 - end |
|
273 - |
|
274 def start |
|
275 # Check the sysidcfg stuff |
|
276 + if ['5.10'].include? Facter.value(:kernelrelease) |
|
277 if cfg = @resource[:sysidcfg] |
|
278 self.fail "Path is required" unless @resource[:path] |
|
279 zoneetc = File.join(@resource[:path], "root", "etc") |
|
280 @@ -273,7 +223,9 @@ |
|
281 end |
|
282 end |
|
283 end |
|
284 + end |
|
285 |
|
286 + # Boots the zone |
|
287 zoneadm :boot |
|
288 end |
|
289 |
|
290 @@ -286,64 +238,35 @@ |
|
291 end |
|
292 |
|
293 main = self.class.line2hash(output.chomp) |
|
294 - |
|
295 - # Now add in the configuration information |
|
296 - config_status.each do |name, value| |
|
297 - main[name] = value |
|
298 - end |
|
299 - |
|
300 main |
|
301 end |
|
302 |
|
303 def ready |
|
304 + # Prepare the zone |
|
305 zoneadm :ready |
|
306 end |
|
307 |
|
308 def stop |
|
309 - zoneadm :halt |
|
310 + # Shutdown the zone |
|
311 + zoneadm :halt |
|
312 end |
|
313 + |
|
314 |
|
315 def unconfigure |
|
316 + # Unconfigure and delete the zone |
|
317 zonecfg :delete, "-F" |
|
318 end |
|
319 |
|
320 def uninstall |
|
321 + # Uninstall the zone |
|
322 zoneadm :uninstall, "-F" |
|
323 end |
|
324 |
|
325 private |
|
326 |
|
327 - # Turn the results of getconfig into status information. |
|
328 - def config_status |
|
329 - config = getconfig |
|
330 - result = {} |
|
331 - |
|
332 - result[:autoboot] = config[:autoboot] ? config[:autoboot].intern : :true |
|
333 - result[:pool] = config[:pool] |
|
334 - result[:shares] = config[:shares] |
|
335 - if dir = config["inherit-pkg-dir"] |
|
336 - result[:inherit] = dir.collect { |dirs| dirs[:dir] } |
|
337 - end |
|
338 - if datasets = config["dataset"] |
|
339 - result[:dataset] = datasets.collect { |dataset| dataset[:name] } |
|
340 - end |
|
341 - result[:iptype] = config[:'ip-type'] if config[:'ip-type'] |
|
342 - if net = config["net"] |
|
343 - result[:ip] = net.collect do |params| |
|
344 - if params[:defrouter] |
|
345 - "#{params[:physical]}:#{params[:address]}:#{params[:defrouter]}" |
|
346 - elsif params[:address] |
|
347 - "#{params[:physical]}:#{params[:address]}" |
|
348 - else |
|
349 - params[:physical] |
|
350 - end |
|
351 - end |
|
352 - end |
|
353 - |
|
354 - result |
|
355 - end |
|
356 - |
|
357 def zoneadm(*cmd) |
|
358 + # Execute the zoneadm command with the arguments |
|
359 + # provided |
|
360 adm("-z", @resource[:name], *cmd) |
|
361 rescue Puppet::ExecutionFailure => detail |
|
362 self.fail "Could not #{cmd[0]} zone: #{detail}" |
|