--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/puppet/patches/puppet-03-zone-provider.patch Mon Sep 23 10:03:20 2013 -0700
@@ -0,0 +1,362 @@
+Enhance the zone provider to configure zones using a zonecfg export file format.
+Enhance the output of puppet resource zone, and fix zone clone functionality.
+--- puppet-3.2.4/lib/puppet/provider/zone/solaris.rb.orig 2013-07-29 15:48:58.118553584 -0600
++++ puppet-3.2.4/lib/puppet/provider/zone/solaris.rb 2013-07-29 15:49:21.053204412 -0600
+@@ -1,5 +1,5 @@
+ Puppet::Type.type(:zone).provide(:solaris) do
+- desc "Provider for Solaris Zones."
++ desc "Provider for Solaris zones."
+
+ commands :adm => "/usr/sbin/zoneadm", :cfg => "/usr/sbin/zonecfg"
+ defaultfor :osfamily => :solaris
+@@ -8,20 +8,20 @@
+
+ # Convert the output of a list into a hash
+ def self.line2hash(line)
+- fields = [:id, :name, :ensure, :path, :uuid, :brand, :iptype]
++ fields = [:id, :name, :ensure, :zonepath, :uuid, :brand, :iptype ]
+ properties = Hash[fields.zip(line.split(':'))]
+
+- del_id = [:brand, :uuid]
++ del_id = [:id, :uuid]
++
+ # Configured but not installed zones do not have IDs
+ del_id << :id if properties[:id] == "-"
+ del_id.each { |p| properties.delete(p) }
+-
+ properties[:ensure] = properties[:ensure].intern
+- properties[:iptype] = 'exclusive' if properties[:iptype] == 'excl'
+
+ properties
+ end
+
++
+ def self.instances
+ # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
+ x = adm(:list, "-cp").split("\n").collect do |line|
+@@ -29,109 +29,64 @@
+ end
+ end
+
+- def multi_conf(name, should, &action)
+- has = properties[name]
+- has = [] if has == :absent
+- rms = has - should
+- adds = should - has
+- (rms.map{|o| action.call(:rm,o)} + adds.map{|o| action.call(:add,o)}).join("\n")
+- end
+-
+- def self.def_prop(var, str)
+- define_method('%s_conf' % var.to_s) do |v|
+- str % v
+- end
+- define_method('%s=' % var.to_s) do |v|
+- setconfig self.send( ('%s_conf'% var).intern, v)
+- end
+- end
++
++ # Read in the zone configuration parameters and properties and
++ # perform the zone configuration. Options are cloning the zone,
++ # which needs a zonecfg_export file, configuring an archive, which
++ # takes optional zonecfg_export and archived_zonename parameters,
++ # or performing a zone configuration, which requires a zonecfg_export
++ # file or string.
++ def configure
+
+- def self.def_multiprop(var, &conf)
+- define_method(var.to_s) do |v|
+- o = properties[var]
+- return '' if o.nil? or o == :absent
+- o.join(' ')
+- end
+- define_method('%s=' % var.to_s) do |v|
+- setconfig self.send( ('%s_conf'% var).intern, v)
+- end
+- define_method('%s_conf' % var.to_s) do |v|
+- multi_conf(var, v, &conf)
++ if @resource[:archive].nil? && @resource[:zonecfg_export].nil?
++ raise Puppet::Error, "No configuration resource is defined."
+ end
+- end
+
+- def_prop :iptype, "set ip-type=%s"
+- def_prop :autoboot, "set autoboot=%s"
+- def_prop :path, "set zonepath=%s"
+- def_prop :pool, "set pool=%s"
+- def_prop :shares, "add rctl\nset name=zone.cpu-shares\nadd value (priv=privileged,limit=%s,action=none)\nend"
+-
+- def_multiprop :ip do |action, str|
+- interface, ip, defrouter = str.split(':')
+- case action
+- when :add
+- cmd = ["add net"]
+- cmd << "set physical=#{interface}" if interface
+- cmd << "set address=#{ip}" if ip
+- cmd << "set defrouter=#{defrouter}" if defrouter
+- cmd << "end"
+- cmd.join("\n")
+- when :rm
+- if ip
+- "remove net address=#{ip}"
+- elsif interface
+- "remove net physical=#{interface}"
+- else
+- raise ArgumentError, "can not remove network based on default router"
++ command = String.new
++ if @resource[:clone]
++ if !@resource[:zonecfg_export]
++ raise Puppet::Error, "A zone configuration must be defined to
++ clone a zone."
++ end
++ command = "#{command(:cfg)} -z #{@resource[:name]} -f #{@resource[:zonecfg_export]}"
++ else
++ unless @resource[:zonecfg_export].nil? || @resource[:zonecfg_export].empty?
++ begin
++ file = File.open(@resource[:zonecfg_export], "rb")
++ str = file.read.gsub(/[\n]\n*\s*/, "; ")
++ rescue
++ str = @resource[:zonecfg_export].gsub(/[\n]\n*\s*/, "; ")
++ ensure
++ file.close unless file.nil?
++ end
++ @property_hash.clear
+ end
+- else self.fail action
+- end
+- end
+
+- def_multiprop :dataset do |action, str|
+- case action
+- when :add; ['add dataset',"set name=#{str}",'end'].join("\n")
+- when :rm; "remove dataset name=#{str}"
+- else self.fail action
+- end
+- end
++ unless @resource[:archive].nil? || @resource[:archive].empty?
++ if !str.nil?
++ command = "#{command(:cfg)} -z #{@resource[:name]} \'create -a #{@resource[:archive]};#{str}\'"
++ else
++ command = "#{command(:cfg)} -z #{@resource[:name]} create -a #{@resource[:archive]} "
++ end
++ if @resource[:archived_zonename]
++ command << " -z #{@resource[:archived_zonename]}"
++ end
++ end
+
+- def_multiprop :inherit do |action, str|
+- case action
+- when :add; ['add inherit-pkg-dir', "set dir=#{str}",'end'].join("\n")
+- when :rm; "remove inherit-pkg-dir dir=#{str}"
+- else self.fail action
++ if !@resource[:zonecfg_export].nil? && @resource[:archive].nil?
++ command = "#{command(:cfg)} -z #{@resource[:name]} \'#{str}\'"
++ end
+ end
+- end
+
+- def my_properties
+- [:path, :iptype, :autoboot, :pool, :shares, :ip, :dataset, :inherit]
+- end
+-
+- # Perform all of our configuration steps.
+- def configure
+- self.fail "Path is required" unless @resource[:path]
+- arr = ["create -b #{@resource[:create_args]}"]
+-
+- # Then perform all of our configuration steps. It's annoying
+- # that we need this much internal info on the resource.
+- self.resource.properties.each do |property|
+- next unless my_properties.include? property.name
+- method = (property.name.to_s + '_conf').intern
+- arr << self.send(method ,@resource[property.name]) unless property.safe_insync?(properties[property.name])
++ if command
++ r = exec_cmd(:cmd => command)
+ end
+- setconfig(arr.join("\n"))
+ end
+
+ def destroy
+ zonecfg :delete, "-F"
+ end
+
+- def add_cmd(cmd)
+- @cmds = [] if @cmds.nil?
+- @cmds << cmd
+- end
+-
+ def exists?
+ properties[:ensure] != :absent
+ end
+@@ -139,31 +94,31 @@
+ # We cannot use the execpipe in util because the pipe is not opened in
+ # read/write mode.
+ def exec_cmd(var)
+- # In bash, the exit value of the last command is the exit value of the
+- # entire pipeline
+- out = execute("echo \"#{var[:input]}\" | #{var[:cmd]}", :failonfail => false, :combine => true)
+- st = $?.exitstatus
+- {:out => out, :exit => st}
+- end
+-
+- # Clear out the cached values.
+- def flush
+- return if @cmds.nil? || @cmds.empty?
+- str = (@cmds << "commit" << "exit").join("\n")
+- @cmds = []
+- @property_hash.clear
+-
+- command = "#{command(:cfg)} -z #{@resource[:name]} -f -"
+- r = exec_cmd(:cmd => command, :input => str)
+- if r[:exit] != 0 or r[:out] =~ /not allowed/
+- raise ArgumentError, "Failed to apply configuration"
++ if var[:input]
++ execute("echo \"#{var[:input]}\" | #{var[:cmd]}", :failonfail => true, :combine => true)
++ else
++ execute("#{var[:cmd]}", :failonfail => true, :combine => true)
+ end
+ end
+
++
+ def install(dummy_argument=:work_arround_for_ruby_GC_bug)
++ if ['5.11', '5.12'].include? Facter.value(:kernelrelease)
++ if !@resource[:install_args] and @resource[:config_profile]
++ @resource[:install_args] = " -c " + @resource[:config_profile]
++ elsif !@resource[:install_args] and @resource[:archive]
++ @resource[:install_args] = " -a " + @resource[:archive]
++ if @resource[:archived_zonename]
++ @resource[:install_args] << " -z " + @resource[:archived_zonename]
++ end
++ elsif @resource[:config_profile]
++ @resource[:install_args] << " -c " + @resource[:config_profile]
++ end
++ end
++
+ if @resource[:clone] # TODO: add support for "-s snapshot"
+- zoneadm :clone, @resource[:clone]
+- elsif @resource[:install_args]
++ zoneadm :clone, @resource[:clone]
++ elsif @resource[:install_args]
+ zoneadm :install, @resource[:install_args].split(" ")
+ else
+ zoneadm :install
+@@ -183,11 +138,12 @@
+ end
+ end
+ @property_hash.dup
++
+ end
+
+ # We need a way to test whether a zone is in process. Our 'ensure'
+ # property models the static states, but we need to handle the temporary ones.
+- def processing?
++ def processing?
+ hash = status
+ return false unless hash
+ ["incomplete", "ready", "shutting_down"].include? hash[:ensure]
+@@ -215,7 +171,6 @@
+ #
+ def getconfig
+ output = zonecfg :info
+-
+ name = nil
+ current = nil
+ hash = {}
+@@ -245,14 +200,9 @@
+ hash
+ end
+
+- # Execute a configuration string. Can't be private because it's called
+- # by the properties.
+- def setconfig(str)
+- add_cmd str
+- end
+-
+ def start
+ # Check the sysidcfg stuff
++ if ['5.10'].include? Facter.value(:kernelrelease)
+ if cfg = @resource[:sysidcfg]
+ self.fail "Path is required" unless @resource[:path]
+ zoneetc = File.join(@resource[:path], "root", "etc")
+@@ -273,7 +223,9 @@
+ end
+ end
+ end
++ end
+
++ # Boots the zone
+ zoneadm :boot
+ end
+
+@@ -286,64 +238,35 @@
+ end
+
+ main = self.class.line2hash(output.chomp)
+-
+- # Now add in the configuration information
+- config_status.each do |name, value|
+- main[name] = value
+- end
+-
+ main
+ end
+
+ def ready
++ # Prepare the zone
+ zoneadm :ready
+ end
+
+ def stop
+- zoneadm :halt
++ # Shutdown the zone
++ zoneadm :halt
+ end
++
+
+ def unconfigure
++ # Unconfigure and delete the zone
+ zonecfg :delete, "-F"
+ end
+
+ def uninstall
++ # Uninstall the zone
+ zoneadm :uninstall, "-F"
+ end
+
+ private
+
+- # Turn the results of getconfig into status information.
+- def config_status
+- config = getconfig
+- result = {}
+-
+- result[:autoboot] = config[:autoboot] ? config[:autoboot].intern : :true
+- result[:pool] = config[:pool]
+- result[:shares] = config[:shares]
+- if dir = config["inherit-pkg-dir"]
+- result[:inherit] = dir.collect { |dirs| dirs[:dir] }
+- end
+- if datasets = config["dataset"]
+- result[:dataset] = datasets.collect { |dataset| dataset[:name] }
+- end
+- result[:iptype] = config[:'ip-type'] if config[:'ip-type']
+- if net = config["net"]
+- result[:ip] = net.collect do |params|
+- if params[:defrouter]
+- "#{params[:physical]}:#{params[:address]}:#{params[:defrouter]}"
+- elsif params[:address]
+- "#{params[:physical]}:#{params[:address]}"
+- else
+- params[:physical]
+- end
+- end
+- end
+-
+- result
+- end
+-
+ def zoneadm(*cmd)
++ # Execute the zoneadm command with the arguments
++ # provided
+ adm("-z", @resource[:name], *cmd)
+ rescue Puppet::ExecutionFailure => detail
+ self.fail "Could not #{cmd[0]} zone: #{detail}"