Enhance the zone type to configure zones using a zonecfg export file format.
Enhance the output of the puppet resource zone.

--- puppet-3.8.6/lib/puppet/type/zone.rb.orig	2016-04-19 14:14:44.165798357 -0700
+++ puppet-3.8.6/lib/puppet/type/zone.rb	2016-04-19 14:15:24.531067353 -0700
@@ -1,10 +1,9 @@
-require 'puppet/property/list'
-Puppet::Type.newtype(:zone) do
-  @doc = "Manages Solaris zones.
+#######################################################################
+# Oracle has modified the originally distributed contents of this file.
+#######################################################################
 
-**Autorequires:** If Puppet is managing the directory specified as the root of
-the zone's filesystem (with the `path` attribute), the zone resource will
-autorequire that directory."
+Puppet::Type.newtype(:zone) do
+  @doc = "Manages Solaris zones."
 
 module Puppet::Zone
   class StateMachine
@@ -59,7 +58,7 @@
 
     def self.fsm
       return @fsm if @fsm
-      @fsm = Puppet::Zone::StateMachine.new
+      @fsm = Puppet::Zone::StateMachine.new 
     end
 
     def self.alias_state(values)
@@ -75,7 +74,7 @@
 
     # This is seq value because the order of declaration is important.
     # i.e we go linearly from :absent -> :configured -> :installed -> :running
-    seqvalue :absent, :down => :destroy
+    seqvalue :absent, :down => :unconfigure
     seqvalue :configured, :up => :configure, :down => :uninstall
     seqvalue :installed, :up => :install, :down => :stop
     seqvalue :running, :up => :start
@@ -104,10 +103,10 @@
         sleep 1
       end
       provider.send(method)
-      provider.flush()
     end
 
     def sync
+
       method = nil
       direction = up? ? :up : :down
 
@@ -131,132 +130,34 @@
 
   newparam(:name) do
     desc "The name of the zone."
-
     isnamevar
   end
 
-  newparam(:id) do
-    desc "The numerical ID of the zone.  This number is autogenerated
-      and cannot be changed."
-  end
-
-  newparam(:clone) do
-    desc "Instead of installing the zone, clone it from another zone.
-      If the zone root resides on a zfs file system, a snapshot will be
-      used to create the clone; if it resides on a ufs filesystem, a copy of the
-      zone will be used. The zone from which you clone must not be running."
-  end
-
-  newproperty(:ip, :parent => Puppet::Property::List) do
-    require 'ipaddr'
-
-    desc "The IP address of the zone.  IP addresses **must** be specified
-      with an interface, and may optionally be specified with a default router
-      (sometimes called a defrouter). The interface, IP address, and default
-      router should be separated by colons to form a complete IP address string.
-      For example: `bge0:192.168.178.200` would be a valid IP address string
-      without a default router, and `bge0:192.168.178.200:192.168.178.1` adds a
-      default router to it.
-
-      For zones with multiple interfaces, the value of this attribute should be
-      an array of IP address strings (each of which must include an interface
-      and may include a default router)."
-
-    # The default action of list should is to lst.join(' '). By specifying
-    # @should, we ensure the should remains an array. If we override should, we
-    # should also override insync?() -- property/list.rb
-    def should
-      @should
-    end
-
-    # overridden so that we match with self.should
-    def insync?(is)
-      is = [] if !is || is == :absent
-      is.sort == self.should.sort
-    end
-  end
-
-  newproperty(:iptype) do
-    desc "The IP stack type of the zone."
-    defaultto :shared
-    newvalue :shared
-    newvalue :exclusive
-  end
-
-  newproperty(:autoboot, :boolean => true) do
-    desc "Whether the zone should automatically boot."
-    defaultto true
-    newvalues(:true, :false)
-  end
-
-  newproperty(:path) do
-    desc "The root of the zone's filesystem.  Must be a fully qualified
-      file name.  If you include `%s` in the path, then it will be
-      replaced with the zone's name.  Currently, you cannot use
-      Puppet to move a zone. Consequently this is a readonly property."
-
-    validate do |value|
-      raise ArgumentError, "The zone base must be fully qualified" unless value =~ /^\//
-    end
-
-    munge do |value|
-      if value =~ /%s/
-        value % @resource[:name]
-      else
-        value
-      end
-    end
+  newparam(:config_profile) do
+    desc "Path to the config_profile to use to configure a solaris zone.
+          This is set when providing a sysconfig profile instead of running the
+	  sysconfig SCI tool on first boot of the zone."
   end
 
-  newproperty(:pool) do
-    desc "The resource pool for this zone."
+  newparam(:zonecfg_export) do
+    desc "Contains the zone configuration information. This can be passed in
+    in the form of a file generated by the zonecfg command, in the form
+    of a template, or a string."
   end
 
-  newproperty(:shares) do
-    desc "Number of FSS CPU shares allocated to the zone."
+  newparam(:archive) do
+    desc "The archive file containing an archived zone."
   end
 
-  newproperty(:dataset, :parent => Puppet::Property::List ) do
-    desc "The list of datasets delegated to the non-global zone from the
-      global zone.  All datasets must be zfs filesystem names which are
-      different from the mountpoint."
-
-    def should
-      @should
-    end
-
-    # overridden so that we match with self.should
-    def insync?(is)
-      is = [] if !is || is == :absent
-      is.sort == self.should.sort
-    end
-
-    validate do |value|
-      unless value !~ /^\//
-        raise ArgumentError, "Datasets must be the name of a zfs filesystem"
-      end
-    end
+  newparam(:archived_zonename) do
+    desc "The archived zone to configure and install"
   end
-
-  newproperty(:inherit, :parent => Puppet::Property::List) do
-    desc "The list of directories that the zone inherits from the global
-      zone.  All directories must be fully qualified."
-
-    def should
-      @should
-    end
-
-    # overridden so that we match with self.should
-    def insync?(is)
-      is = [] if !is || is == :absent
-      is.sort == self.should.sort
-    end
-
-    validate do |value|
-      unless value =~ /^\//
-        raise ArgumentError, "Inherited filesystems must be fully qualified"
-      end
-    end
+  
+  newparam(:clone) do
+    desc "Instead of installing the zone, clone it from another zone.
+      If the zone root resides on a zfs file system, a snapshot will be
+      used to create the clone; if it resides on a ufs filesystem, a copy of the
+      zone will be used. The zone from which you clone must not be running."
   end
 
   # Specify the sysidcfg file.  This is pretty hackish, because it's
@@ -293,70 +194,11 @@
       so Puppet only checks for it at that time.}
   end
 
-  newparam(:create_args) do
-    desc "Arguments to the `zonecfg` create command.  This can be used to create branded zones."
-  end
-
   newparam(:install_args) do
     desc "Arguments to the `zoneadm` install command.  This can be used to create branded zones."
   end
 
-  newparam(:realhostname) do
-    desc "The actual hostname of the zone."
-  end
-
-  # If Puppet is also managing the base dir or its parent dir, list them
-  # both as prerequisites.
-  autorequire(:file) do
-    if @parameters.include? :path
-      [@parameters[:path].value, ::File.dirname(@parameters[:path].value)]
-    else
-      nil
-    end
-  end
-
-  # If Puppet is also managing the zfs filesystem which is the zone dataset
-  # then list it as a prerequisite.  Zpool's get autorequired by the zfs
-  # type.  We just need to autorequire the dataset zfs itself as the zfs type
-  # will autorequire all of the zfs parents and zpool.
-  autorequire(:zfs) do
-    # Check if we have datasets in our zone configuration and autorequire each dataset
-    self[:dataset] if @parameters.include? :dataset
-  end
-
-  def validate_ip(ip, name)
-    IPAddr.new(ip) if ip
-  rescue ArgumentError
-    self.fail Puppet::Error, "'#{ip}' is an invalid #{name}", $!
-  end
-
-  def validate_exclusive(interface, address, router)
-    return if !interface.nil? and address.nil?
-    self.fail "only interface may be specified when using exclusive IP stack: #{interface}:#{address}"
-  end
-  def validate_shared(interface, address, router)
-    self.fail "ip must contain interface name and ip address separated by a \":\"" if interface.nil? or address.nil?
-    [address, router].each do |ip|
-      validate_ip(address, "IP address") unless ip.nil?
-    end
-  end
-
-  validate do
-    return unless self[:ip]
-    # self[:ip] reflects the type passed from proeprty:ip.should. If we
-    # override it and pass @should, then we get an array here back.
-    self[:ip].each do |ip|
-      interface, address, router = ip.split(':')
-      if self[:iptype] == :shared
-        validate_shared(interface, address, router)
-      else
-        validate_exclusive(interface, address, router)
-      end
-    end
-  end
-
   def retrieve
-    provider.flush
     hash = provider.properties
     return setstatus(hash) unless hash.nil? or hash[:ensure] == :absent
     # Return all properties as absent.
@@ -379,4 +221,25 @@
     end
     prophash
   end
+
+  # Private Properties
+  # The following properties are used in conjunction with the "puppet resource zone"
+  # output. They are valid properties for configuring a zone.
+
+  newproperty(:id) do
+    desc "The numerical ID of the zone.  This number is autogenerated
+    and cannot be changed."
+  end
+
+  newproperty(:zonepath) do
+    desc "The path to zone's file system."
+  end
+
+  newproperty(:iptype) do
+    desc "Displays exclusive or shared instance of IP."
+  end
+
+  newproperty(:brand) do
+    desc "The zone's brand type"
+  end
 end
