components/puppet/patches/puppet-03-zone-provider.patch
author Drew Fisher <drew.fisher@oracle.com>
Fri, 31 Jan 2014 14:12:10 -0700
branchs11-update
changeset 2928 43b3da52b84a
parent 2771 8e4227dc2fc4
permissions -rw-r--r--
PSARC 2013/426 Puppet 3.4.1 17783988 Add zone.rb to Facter 17798202 Several providers return errors due to Ruby 1.9 changes. 17945378 backport of 17257851 to 11.2 was never actually done 18010466 Update Puppet to 3.4.1

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.4.1/lib/puppet/provider/zone/solaris.rb.orig	2013-07-29 15:48:58.118553584 -0600
+++ puppet-3.4.1/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}"