class Junos::Ez::Provider::Parent

Attributes

catalog[RW]
has[RW]
list[RW]
name[R]
ndev[R]
parent[R]
properties[RW]
providers[RW]
should[RW]

Public Class Methods

new( p_obj, name = nil, opts = {} ) click to toggle source

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 ) click to toggle source

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, rval ) click to toggle source

[]= 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
activate!() click to toggle source

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?() click to toggle source

'active?' - is the resource config active in Junos


# File lib/junos-ez/provider.rb, line 160
def active?
  false unless exists?
  @has[:_active]
end
catalog!() click to toggle source
# File lib/junos-ez/provider.rb, line 191
def catalog!
  @catalog.clear
  @catalog = build_catalog
end
create( name = nil, prop_hash = {} ) { |newbie| ... } click to toggle source

'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!( *args ) click to toggle source

'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
create_from_hash!( as_hash, opts = {} ) click to toggle source
# 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
create_from_yaml!( opts = {} ) click to toggle source

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
deactivate!() click to toggle source
# File lib/junos-ez/provider.rb, line 305
def deactivate!
  return nil if @should[:_active] == false    
  @should[:_active] = false
  write!
end
delete!() click to toggle source

'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
each( ) { |select(name )| ... } click to toggle source

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?() click to toggle source

'exists?' - does the resource exist in the Juos config


# File lib/junos-ez/provider.rb, line 154
def exists?; @has[:_exist]; end
init_has() click to toggle source

'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?() click to toggle source

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?() click to toggle source

'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
list!() click to toggle source
# File lib/junos-ez/provider.rb, line 182
def list!
  @list.clear
  @list = build_list
end
name_decorated( name = @name ) click to toggle source

@@@ 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
need_write?() click to toggle source

Provider writer methods


# File lib/junos-ez/provider.rb, line 432
def need_write?; not @should.empty? end
read!() click to toggle source
# 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
rename!( new_name ) click to toggle source
# 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
reorder!( opts ) click to toggle source

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( name ) click to toggle source

'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( which = :read ) click to toggle source

'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
to_h_expanded( opts = {} ) click to toggle source
# File lib/junos-ez/provider.rb, line 268
def to_h_expanded( opts = {} ) 
  to_h( opts ) 
end
to_yaml( opts = {} ) click to toggle source
# 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
with( given_list ) { |select( name )| ... } click to toggle source

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
write!() click to toggle source
# 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_at_edit() click to toggle source

XML writer methods


# File lib/junos-ez/provider.rb, line 464
def xml_at_edit; nil; end
xml_at_top() click to toggle source
# File lib/junos-ez/provider.rb, line 465
def xml_at_top; nil; end
xml_build_change( xml_at_here = nil ) click to toggle source

'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
xml_change__active( xml ) click to toggle source
# 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
xml_change__exist( xml ) click to toggle source
# 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_change_admin( xml ) click to toggle source

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
xml_change_description( xml ) click to toggle source
# 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!() click to toggle source

'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
xml_element_newname( new_name) click to toggle source

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( xml ) click to toggle source

'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
xml_on_create( xml ) click to toggle source
# File lib/junos-ez/provider.rb, line 466
def xml_on_create( xml ); nil; end
xml_on_delete( xml ) click to toggle source
# File lib/junos-ez/provider.rb, line 467
def xml_on_delete( xml ); nil; end

Private Instance Methods

diff_property_array( prop ) click to toggle source
# File lib/junos-ez/provider.rb, line 611
def diff_property_array( prop )
  should = @should[prop] || []
  has = @has[prop] || []
  [ should - has,  has - should ]
end
oh_no!() { || ... } click to toggle source
# 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
set_has_status( xml, has ) click to toggle source

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

!!!!! 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_xml_config!( xml, opts = {} ) click to toggle source

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_read_parse_noele( as_xml, ele_name, as_hash, prop ) click to toggle source

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_set_or_delete( xml, ele_name, value ) click to toggle source

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
xml_set_or_delete_element( xml, ele_name, should ) click to toggle source
# 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
xml_set_or_delete_noele( xml, ele_name, prop = ele_name.to_sym ) click to toggle source
# 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
xml_when_item( xml_item ) { |xml_item| ... } click to toggle source
# 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