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