class Junos::Ez::Provider::Parent
Attributes
Public Class Methods
p_obj - the parent object name - the name of the resource, or nil if this is a provider opts - options to the provider/resource. :parent is reserved
# File lib/junos-ez/provider.rb, line 82 def initialize( p_obj, name = nil, opts = {} ) @providers = [] @parent = opts[:parent] || nil @ndev = p_obj.instance_variable_get(:@ndev) || p_obj @name = name @opts = opts @list = [] # array list of item names @catalog = {} # hash catalog of named items return unless @name # resources only from here ... @has = {} # properties read-from Junos @should = {} # properties to write-back to Junos end
Public Instance Methods
- property
-
resource property reader or
- “name”
-
resource selector from provider
# File lib/junos-ez/provider.rb, line 117 def []( property ) return self.select( property ) if is_provider? # if there is already something in the write-back, then use # it before using from the read-cache return @should[property] if @should[property] return @has[property] if @has end
[]= property writer (@should)
# File lib/junos-ez/provider.rb, line 131 def []=( property, rval ) raise ArgumentError, "This is not a provider instance" if is_provider? raise ArgumentError, "Invalid property['#{property.to_s}']" unless properties.include? property @should[property] = rval end
Junos
activation controls
# File lib/junos-ez/provider.rb, line 299 def activate! return nil if @should[:_active] == true @should[:_active] = true write! end
'active?' - is the resource config active in Junos
# File lib/junos-ez/provider.rb, line 160 def active? false unless exists? @has[:_active] end
# File lib/junos-ez/provider.rb, line 191 def catalog! @catalog.clear @catalog = build_catalog end
'create' will build a new object, but does not write the contents back to the device. The caller can chain the write! method if desired Alternative, the caller can use 'create!' which does write to the device.
# File lib/junos-ez/provider.rb, line 207 def create( name = nil, prop_hash = {} ) ## if this is an existing object, then we shouldn't ## allow the caller to create something. raise ArgumentError, "Not called by provider!" unless is_provider? ## if we're here, then we're creating an entirely new ## instance of this object. We should check to see if ## it first exists, eh? So allow the caller to specify ## if they want an exception if it already exists; overloading ## the use of the prop_hash[:_exist], yo! newbie = self.select( name ) if prop_hash[:_exist] raise ArgumentError, name_decorated(name) + " already exists" if newbie.exists? end prop_hash.each{ |k,v| newbie[k] = v } unless prop_hash.empty? ## default mark the newly created object as should exist and should ## be active (if not already set) newbie[:_exist] = true newbie[:_active] ||= true ## if a block is provided, then pass the block the new object ## the caller is then expected to set the properies yield( newbie ) if block_given? ## return the new object return newbie end
'create!' is just a helper to call create and then write the config assuming create returns ok.
# File lib/junos-ez/provider.rb, line 247 def create!( *args ) newbie = create( *args ) return nil unless newbie newbie.write! newbie end
# File lib/junos-ez/provider.rb, line 264 def create_from_hash!( as_hash, opts = {} ) write_xml_config! xml_from_h_expanded( as_hash, opts ) end
YAML / HASH methods
# File lib/junos-ez/provider.rb, line 258 def create_from_yaml!( opts = {} ) raise ArgumentError "Missing :filename param" unless opts[:filename] as_hash = YAML.load_file( opts[:filename] ) write_xml_config! xml_from_h_expanded( as_hash, opts ) end
# File lib/junos-ez/provider.rb, line 305 def deactivate! return nil if @should[:_active] == false @should[:_active] = false write! end
'delete!' will cause the item to be removed from the Junos
configuration
# File lib/junos-ez/provider.rb, line 284 def delete! return nil unless exists? xml = xml_at_top par = xml.instance_variable_get(:@parent) par['delete'] = 'delete' xml_on_delete( xml ) rsp = write_xml_config!( xml.doc.root ) @has[:_exist] = false true # rsp ... don't return XML, but let's hear from the community... end
Provider `each` - iterate through each managed resource as obtained from the `list` instance variable. select the object and pass it to the provided block
# File lib/junos-ez/provider.rb, line 364 def each( &block ) raise ArgumentError, "not a provider" unless is_provider? list.each{ |name| yield select(name ) } end
'exists?' - does the resource exist in the Juos config
# File lib/junos-ez/provider.rb, line 154 def exists?; @has[:_exist]; end
'init_has' is called when creating a new managed object or when a caller attempts to retrieve a non-existing one
# File lib/junos-ez/provider.rb, line 387 def init_has; nil end
is_new? - indicates if this is a new resource
# File lib/junos-ez/provider.rb, line 110 def is_new?; (@has[:_exist] == false) || false end
'is_provider?' - indicates if this object instance is a provider object, rather than a specific instance of the object
# File lib/junos-ez/provider.rb, line 104 def is_provider?; @name.nil? end
# File lib/junos-ez/provider.rb, line 182 def list! @list.clear @list = build_list end
@@@ helper method, probably needs to go into 'private section @@@ TBD
# File lib/junos-ez/provider.rb, line 168 def name_decorated( name = @name ) self.class.to_s + "['" + name + "']" end
Provider writer methods
# File lib/junos-ez/provider.rb, line 432 def need_write?; not @should.empty? end
# File lib/junos-ez/provider.rb, line 402 def read! @has.clear cfg_xml = xml_config_read! @has_xml = xml_get_has_xml( cfg_xml ) ## if the thing doesn't exist in Junos, then mark the @has ## structure accordingly and call the object init_has for ## any defaults unless @has_xml @has[:_exist] ||= false @has[:_active] ||= true init_has return nil end ## xml_read_parser *MUST* be implmented by the provider class ## it is used to parse the XML into the HASH structure. It ## returns true/false xml_read_parser( @has_xml, @has ) ## return the Hash representation self.has end
# File lib/junos-ez/provider.rb, line 318 def rename!( new_name ) return nil unless exists? xml = xml_at_top par = xml.instance_variable_get(:@parent) new_ele_name = xml_element_newname( new_name ) return nil unless new_ele_name par['rename'] = 'rename' par['name'] = new_ele_name rsp = write_xml_config!( xml.doc.root ) @name = new_name rsp end
Junos
reorder method
opts = item-name, opts = item-name
# File lib/junos-ez/provider.rb, line 342 def reorder!( opts ) return nil unless exists? ## validate opts hash ctrl, name = opts.first raise ArgumentError, "Invalid operation #{ctrl}" unless [:before,:after].include? ctrl xml = xml_at_top par = xml.instance_variable_get(:@parent) par['insert'] = ctrl.to_s par['name'] = name rsp = write_xml_config! ( xml.doc.root ) return rsp end
'select' a resource from a provider
# File lib/junos-ez/provider.rb, line 142 def select( name ) raise ArgumentError, "This is not a provider instance" unless is_provider? this = self.class.new( @ndev, name, @opts ) this.properties = self.properties this.read! this end
'to_h' lets us look at the read/write hash structures
# File lib/junos-ez/provider.rb, line 520 def to_h( which = :read ) { @name => (which == :read) ? @has : @should } end
# File lib/junos-ez/provider.rb, line 268 def to_h_expanded( opts = {} ) to_h( opts ) end
# File lib/junos-ez/provider.rb, line 272 def to_yaml( opts = {} ) out_hash = to_h_expanded( opts ) out_yaml = out_hash.to_yaml File.open( opts[:filename], "w" ){|f| f.puts out_hash.to_yaml } if opts[:filename] out_yaml end
Provider `with` - iterate through each managed resource as obtained from the `given_list` instance variable.
select the object and pass it to the provided block
# File lib/junos-ez/provider.rb, line 375 def with( given_list, &block ) raise ArgumentError, "not a provider" unless is_provider? given_list.each{ |name| yield select( name ) } end
# File lib/junos-ez/provider.rb, line 434 def write! return nil if @should.empty? @should[:_exist] ||= true # create the necessary chagnes and push them to the Junos # device. If an error occurs, it will be raised xml_change = xml_build_change return nil unless xml_change rsp = write_xml_config!( xml_change ) # copy the 'should' values into the 'has' values now that # they've been written back to Junos @has.merge! @should @should.clear # returning 'true' for now. might need to change this back # to 'rsp' depending on the community feedback. general approach is to not have to # deal with XML, unless it's an exception case. the only time rsp is really # needed is to look at warnings; i.e. not-errors. errors will generate an exception, yo! return true end
XML writer methods
# File lib/junos-ez/provider.rb, line 464 def xml_at_edit; nil; end
# File lib/junos-ez/provider.rb, line 465 def xml_at_top; nil; end
'xml_build_change' is used to create the Junos
XML configuration structure. Generally speaking it should not be called by code outside the providers, but sometimes we might want to, so don't make it private
# File lib/junos-ez/provider.rb, line 483 def xml_build_change( xml_at_here = nil ) edit_at = xml_at_here || xml_at_edit || xml_at_top if @should[:_exist] == false xml_change__exist( edit_at ) return edit_at.doc.root end changed = false @should.keys.each do |prop| changed = true if self.send( "xml_change_#{prop}", edit_at ) end (changed) ? edit_at.doc.root : nil end
# File lib/junos-ez/provider.rb, line 510 def xml_change__active( xml ) par = xml.instance_variable_get(:@parent) value = @should[:_active] ? 'active' : 'inactive' par[value] = value # attribute name is same as value end
# File lib/junos-ez/provider.rb, line 469 def xml_change__exist( xml ) return xml_on_create( xml ) if @should[:_exist] par = xml.instance_variable_get(:@parent) par['delete'] = 'delete' return xml_on_delete( xml ) end
XML common write “change” methods
# File lib/junos-ez/provider.rb, line 502 def xml_change_admin( xml ) xml.disable (@should[:admin] == :up ) ? Netconf::JunosConfig::DELETE : nil end
# File lib/junos-ez/provider.rb, line 506 def xml_change_description( xml ) xml_set_or_delete( xml, 'description', @should[:description] ) end
'xml_config_read!' is ued to retrieve the configuration from the Junos
device
# File lib/junos-ez/provider.rb, line 398 def xml_config_read! @ndev.rpc.get_configuration( xml_at_top ) end
by default, simply allow the new name
# File lib/junos-ez/provider.rb, line 316 def xml_element_newname( new_name); new_name end
'xml_get_has_xml' - used to retrieve the starting location of the actual XML data for the managed object (as compared to the top of the configuration document
# File lib/junos-ez/provider.rb, line 393 def xml_get_has_xml( xml ); nil end
# File lib/junos-ez/provider.rb, line 466 def xml_on_create( xml ); nil; end
# File lib/junos-ez/provider.rb, line 467 def xml_on_delete( xml ); nil; end
Private Instance Methods
# File lib/junos-ez/provider.rb, line 611 def diff_property_array( prop ) should = @should[prop] || [] has = @has[prop] || [] [ should - has, has - should ] end
# File lib/junos-ez/provider.rb, line 555 def oh_no! return if @opts[:ignore_raise] yield if block_given? # should always be a block given ... end
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!! PRIVATE METHODS !!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# File lib/junos-ez/provider.rb, line 530 def set_has_status( xml, has ) has[:_active] = xml['inactive'] ? false : true has[:_exist] = true end
write configuration to Junos
. Check for errors vs. warnings. if there are warnings then return the result. If there are errors, re-throw the exception object. If everything was OK, simply return the result
# File lib/junos-ez/provider.rb, line 542 def write_xml_config!( xml, opts = {} ) begin action = {'action' => 'replace' } result = @ndev.rpc.load_configuration( xml, action ) rescue Netconf::RpcError => e errs = e.rsp.xpath('//rpc-error') raise e unless errs.empty? e.rsp else result end end
XML property reader/writer for elements that can be present, or existing with a “no-” prepended. For example “retain” or “no-retain”
# File lib/junos-ez/provider.rb, line 566 def xml_read_parse_noele( as_xml, ele_name, as_hash, prop ) unless (ele = as_xml.xpath("#{ele_name} | no-#{ele_name}")).empty? as_hash[prop] = (ele[0].name =~ /^no-/) ? false : true end end
XML property writer utilities
# File lib/junos-ez/provider.rb, line 603 def xml_set_or_delete( xml, ele_name, value ) xml.send( ele_name.to_sym, (value ? value : Netconf::JunosConfig::DELETE) ) end
# File lib/junos-ez/provider.rb, line 607 def xml_set_or_delete_element( xml, ele_name, should ) xml.send( ele_name.to_sym, (should) ? nil : Netconf::JunosConfig::DELETE ) end
# File lib/junos-ez/provider.rb, line 572 def xml_set_or_delete_noele( xml, ele_name, prop = ele_name.to_sym ) # delete what was there unless @has[prop].nil? value_prop = @has[prop] wr_ele_name = value_prop ? ele_name : 'no-' + ele_name xml.send(wr_ele_name.to_sym, Netconf::JunosConfig::DELETE) end # if we're not adding anything back, signal that we've done # something, and we're done, yo! return true if @should[prop].nil? # add new value value_prop = @should[prop] ele_name = 'no-' + ele_name if value_prop == false xml.send( ele_name.to_sym ) end
# File lib/junos-ez/provider.rb, line 592 def xml_when_item( xml_item, &block ) raise ArgumentError, "no block given" unless block_given? return unless xml_item[0] return yield(xml_item[0]) if block.arity == 1 yield end