class Nim

Public Instance Methods

add_default_route(network_name,gateway) click to toggle source
# File lib/rbvppc/nim.rb, line 438
def add_default_route(network_name,gateway)
   #TODO: Add more robust creation/management of NIM network routes, if necessary
   execute_cmd("nim -o change -a routing1='default #{gateway}' #{network_name}")
end
add_image(file_path,mksysb_name) click to toggle source

Add a mksysb image to this NIM based on the name given and the local file path of the mksysb file on the NIM. Returns the name of the image that is created.

# File lib/rbvppc/nim.rb, line 143
def add_image(file_path,mksysb_name)
   #Check to make sure a mksysb with this name doesn't already exist
   images = list_images
   if images.include?(mksysb_name)
      raise StandardError.new("A mksysb with the specified name #{mksysb_name} already exists, please specify another name")
   end

   #Add image to the NIM
   execute_cmd "nim -o define -t mksysb -F -a server=master -a location=#{file_path} -a mksysb_flags=XAe #{mksysb_name}"

   #Extract a SPOT from this mksysb
   extract_spot(mksysb_name)

   return mksysb_name
end
add_network(network_name,network_addr,snm,gw) click to toggle source

Add a NIM network object using the given name, network address, subnet mask, gateway

# File lib/rbvppc/nim.rb, line 398
def add_network(network_name,network_addr,snm,gw)
   #Ensure that network with this address doesn't already exist
   raise StandardError.new("Network #{network_name} already exists on this NIM") if network_exists?(network_name,network_addr)

   #Execute NIM command to create the network
   #It is assumed that the network addess and the gateway are the same
   execute_cmd("nim -o define -t ent -a net_addr=#{network_addr} -a snm=#{snm} #{network_name}")

   #Add default route to the specified gateway
   add_default_route(network_name,gw)
end
bid_exists?(client_lpar) click to toggle source

Checks if BID object exists on NIM for the Client LPAR

# File lib/rbvppc/nim.rb, line 345
def bid_exists?(client_lpar)
   defined_bids = list_objtype("bosinst_data")
   defined_bids.each do |obj_name|
      #Iterate through array elements returned by list_objtype
      #and check if any of them line up with the BID name for our LPAR
      if (obj_name == "#{client_lpar.name}_bid")
      #if (obj_name == "#{client_lpar}_bid")
         return true
      end
   end
   return false
end
bos_install_finished?(lpar) click to toggle source

Used in populating the BOS Install status message Returns true of the specified lpar is done with is BOS build. Sleeps for 15 seconds and returns false if otherwise.

# File lib/rbvppc/nim.rb, line 230
def bos_install_finished?(lpar)
   if check_install_status(lpar).match(/ready for a NIM operation/i)
      return true
   else
      sleep 15
      return false
   end
end
capture_image(source_lpar,mksysb_name,path) click to toggle source

Capture a mksysb image from a NIM client

# File lib/rbvppc/nim.rb, line 132
def capture_image(source_lpar,mksysb_name,path)
   #Pull mksysb from a NIM client, give it a name and place it in some location on the NIM
   execute_cmd "nim -o define -t mksysb -F -a server=master -a location=#{path} -a source=#{source_lpar.name} -a mk_image=yes -a mksysb_flags=XAe #{mksysb_name}"
         
   #Create SPOT resource from this mksysb, giving it a name and a location on the NIM to store it
   extract_spot(mksysb_name)     
end
check_install_status(client_lpar) click to toggle source

Check the install status of a NIM client Returns current Cstate attribute of NIM client

# File lib/rbvppc/nim.rb, line 111
def check_install_status(client_lpar)
   #lsnim -Z -a Cstate -a Mstate -a Cstate_result -a info nim_client_name
   result = execute_cmd "lsnim -Z -a Cstate -a Mstate -a Cstate_result -a info #{client_lpar.name}"
   #result = execute_cmd "lsnim -Z -a Cstate -a Mstate -a Cstate_result -a info #{client_lpar}"
   result.each_line do |line|
      line.match(/#{client_lpar.name}/) do |m|
      #line.match(/#{client_lpar}/) do |m|
         #Cstate is the 2nd column of the : delimited output
         cstate = line.split(/:/)[1]
         return cstate
      end
   end
   return nil
end
client_defined?(client_lpar) click to toggle source

Is the NIM Client defined?

# File lib/rbvppc/nim.rb, line 54
def client_defined?(client_lpar)
   #lsnim -Z lpar_name_here 2>/dev/null | awk '(NR==2) {print $1}' | awk -F: '{print $2}'
   #result = execute_cmd "lsnim -Z #{client_lpar} 2>/dev/null | " +
   result = execute_cmd "lsnim -Z #{client_lpar.name} 2>/dev/null | " +
                          "awk '(NR==2) {print $1}' | awk -F: '{print $2}'"
   return result.chomp == "machines"
end
create_bid(client_lpar) click to toggle source

Creates a bosinst_data object for the client_lpar specified

# File lib/rbvppc/nim.rb, line 303
   def create_bid(client_lpar)
      if bid_exists?(client_lpar)
         #Force remove the BID and then continue to create a new one.
         remove_bid(client_lpar)
      end
      
      #Use heredoc to populate the bosinst_data file in a multiline string
      bid_contents = <<-EOS
      # bosinst_data file created for #{client_lpar.name}
      
      CONSOLE = Default
      RECOVER_DEVICES = no
      INSTALL_METHOD = overwrite
      PROMPT = no
      EXISTING_SYSTEM_OVERWRITE = any
      ACCEPT_LICENSES = yes
      
      locale:
      BOSINST_LANG = en_US
      CULTURAL_CONVENTION = en_US
      MESSAGES = en_US
      KEYBOARD = en_US
      EOS
      
      #Create bid contents file on NIM
      execute_cmd "mkdir -p /darwin; echo '#{bid_contents}' > /darwin/#{client_lpar.name}_bid"
      
      
      #Define the BID object
      execute_cmd "nim -o define -t bosinst_data -a location=/darwin/#{client_lpar.name}_bid -a server=master #{client_lpar.name}_bid"
      
      #Return the name of the BID created
      return "#{client_lpar.name}_bid"      
   end
deallocate_resources(client_lpar) click to toggle source

Deallocates any/all NIM resources from the client manchine

# File lib/rbvppc/nim.rb, line 99
def deallocate_resources(client_lpar)
   execute_cmd "nim -o deallocate -a subclass=all #{client_lpar.name}"
end
define_client(client_lpar) click to toggle source

Define the NIM Client

# File lib/rbvppc/nim.rb, line 63
def define_client(client_lpar)
   if client_defined?(client_lpar)
      remove_client(client_lpar)
   end
   execute_cmd %Q{nim -o define -t standalone -a if1="find_net #{client_lpar.hostname} #{client_lpar.get_mac_address}" -a cable_type1="N/A" -a platform=chrp -a comments="Built by Darwin" -a net_settings1="auto auto" -a connect="shell" -a netboot_kernel=#{master_netboot_kernel} #{client_lpar.name}}
   #execute_cmd %Q{nim -o define -t standalone -a if1="find_net #{hostname} #{mac}" -a cable_type1="N/A" -a platform=chrp -a comments="Built by Darwin" -a net_settings1="auto auto" -a connect="shell" -a netboot_kernel=#{master_netboot_kernel} #{client_lpar}}
end
deploy_image(client_lpar, mksysb_name, firstboot_script = nil, lpp_source = nil) { |nim_ip,gateway,subnetmask| ... } click to toggle source

Deploy mksysb image to NIM client

# File lib/rbvppc/nim.rb, line 180
def deploy_image(client_lpar, mksysb_name, firstboot_script = nil, lpp_source = nil)
   
   bosinst_data_obj = client_lpar.name+"_bid"
   
   #Create a NIM Client and a bosinst_data object if they don't
   #already exist for this LPAR.
   define_client(client_lpar) if !client_defined?(client_lpar)      
   create_bid(client_lpar) if !bid_exists?(client_lpar)

   if !lpp_source.nil?
      #TODO: Do something different if an lpp_source is specified...
   end

   #Get the SPOT to use for this image deployment
   spot_name = get_spot(mksysb_name)
   if spot_name.nil?
      #Extract the spot from this mksysb and use it
      spot_name = extract_spot(mksysb_name)
   end

   command = "nim -o bos_inst -a source=mksysb -a mksysb=#{mksysb_name} -a bosinst_data=#{bosinst_data_obj} -a no_nim_client=no " +
             "-a accept_licenses=yes -a boot_client=no"
   command += " -a spot=#{spot_name}" if !spot_name.nil?
   command += " -a fb_script=#{firstboot_script}" if !firstboot_script.nil?
   command += " -a lpp_source=#{lpp_source}" if !lpp_source.nil?
   command += " #{client_lpar.name}"
   #NIM command to start a remote mksysb install on NIM client
   execute_cmd(command)                        
   
   #Then, in order to actually start the install the HMC needs to netboot the LPAR
   #Should that be called from here or just utilized separately from the HMC object?
   #Maybe yeild to a block that should call the HMC LPAR netboot?
   #Then upon returning to this function, we poll the NIM client for Cstate statuses
   #until the build is finished?
   network_name = get_lpar_network_name(client_lpar)
   gateway = get_network_gateway(network_name)
   subnetmask = get_network_subnetmask(network_name)
   nim_ip = get_master_ip      
   
   yield(nim_ip,gateway,subnetmask)
   
   #Implemented nicer looking progress message for BOS installs
   print "Waiting for BOS install for #{client_lpar.name} to finish..."
   print "." until bos_install_finished?(client_lpar)
   puts "done"            
end
execute_cmd(command) click to toggle source

Execute commands on NIM, outputting the full command with puts first.

Calls superclass method ConnectableServer#execute_cmd
# File lib/rbvppc/nim.rb, line 29
def execute_cmd(command)
    puts "#{command}" if debug
    super "#{command}"
end
extract_spot(mksysb_name) click to toggle source

Extracts a SPOT from the mksysb image name specified. places the SPOT in a directory location adjacent to where the mksysb resides If a spot already exists for this mksysb, it's name is simply returned.

# File lib/rbvppc/nim.rb, line 260
def extract_spot(mksysb_name)
   #Find out if this mksysb exists on the NIM
   if !list_objtype("mksysb").include?(mksysb_name)
      #Mksysb not found - error out?
   end

   spot_name = mksysb_name+"_spot"
   #Find out if a SPOT already exists for this mksysb
   #if so, just return that name.
   temp_name = get_spot(mksysb_name)
   if !temp_name.nil?
      return temp_name
   end

   #Get the location of this mksysb
   mksysb_loc = get_mksysb_location(mksysb_name)

   #Make sure the mksysb location is non-null
   raise StandardError.new("Cannot locate where the image #{mksysb_name} exists on this NIM") if mksysb_loc.nil?

   #Split the mksysb location on '/', pop the mksysb name and directory it resides
   #in off of the array and push "spot" and the spot name onto the array to end up placing
   #the SPOT in ../spot/spot_name
   split_mksysb_path = mksysb_loc.split("/")
   split_mksysb_path.pop
   split_mksysb_path.pop
   split_mksysb_path.push("spot")
   split_mksysb_path.push(mksysb_name+"_spot")
   spot_path = split_mksysb_path.join("/")

   #Make a SPOT from this mksysb with the name <mksysb_name>_spot
   execute_cmd("nim -o define -t spot -a server=master -a source=#{mksysb_name} -a location=#{spot_path} -a auto_expand=yes #{spot_name}")

   #Return the name of the SPOT.
   return spot_name
end
get_lpar_network_name(client_lpar) click to toggle source

Find NIM interface settings for client LPAR

# File lib/rbvppc/nim.rb, line 359
def get_lpar_network_name(client_lpar)
   output = execute_cmd "lsnim -Z -a if1 #{client_lpar.name}"
   nim_network=""
   output.each_line do |line|
      line.chomp!
      if line.match(/^#{client_lpar.name}/)
         network_args = line.split(/:/)
         nim_network = network_args[1]
      end
   end
   return nim_network
end
get_master_ip() click to toggle source

Returns the IP address of the NIM master as a String

# File lib/rbvppc/nim.rb, line 78
def get_master_ip
   niminfo_line = execute_cmd("cat /etc/niminfo | grep NIM_MASTER_HOSTNAME")
   hostname = niminfo_line.split("=")[1].chomp

   ipaddr_line = execute_cmd("host #{hostname}")
   ip = ipaddr_line.split(" is ")[1].chomp

   if ip.empty?
      raise StandardError.new("Unable to determine the NIM Master's IP Address")
   end

   return ip
end
get_mksysb_location(mksysb_name) click to toggle source

Returns the filesystem location of the mksysb with the specified name

# File lib/rbvppc/nim.rb, line 240
def get_mksysb_location(mksysb_name)
   execute_cmd("lsnim -l #{mksysb_name} | awk '{if ($1 ~ /location/) print $3}'").chomp
end
get_network_gateway(network_name) click to toggle source

Find Gateway IP for NIM network

# File lib/rbvppc/nim.rb, line 373
def get_network_gateway(network_name)
   output = execute_cmd "lsnim -Z -a net_addr -a snm -a routing #{network_name}"
   output.each_line do |line|
      line.chomp!
      if line.match(/^#{network_name}/)
         network_fields = line.split(/:/)
         return network_fields[-1]
      end
   end
end
get_network_subnetmask(network_name) click to toggle source

Find Subnet mask for NIM network

# File lib/rbvppc/nim.rb, line 385
def get_network_subnetmask(network_name)
   output = execute_cmd "lsnim -Z -a net_addr -a snm -a routing #{network_name}"
   output.each_line do |line|
      line.chomp!
      if line.match(/^#{network_name}/)
         network_fields = line.split(/:/)
         return network_fields[2]
      end
   end
end
get_spot(mksysb_name) click to toggle source

Returns the name of the SPOT extracted from the supplied mksysb

# File lib/rbvppc/nim.rb, line 246
def get_spot(mksysb_name)
   spot = execute_cmd("lsnim -l #{mksysb_name} | awk '{if ($1 ~ /extracted_spot/) print $3}'").chomp
   if spot.empty?
      return nil
   else
      return spot
   end
end
list_images() click to toggle source

Return an array of names of mksysbs that exist on this NIM

# File lib/rbvppc/nim.rb, line 127
def list_images
   list_objtype("mksysb")
end
list_objtype(type) click to toggle source

list all defined objects of a specific type acceptable types are (standalone,ent,lpp_source,mksysb,spot,fb_script,script,bosinst_data,ent)

# File lib/rbvppc/nim.rb, line 36
def list_objtype(type)
   case type
   when "standalone","ent","lpp_source","mksysb","spot","fb_script","script","bosinst_data"
      output = execute_cmd "lsnim -t #{type}"
   else
      raise StandardError.new("Unknown type of NIM Object passed")
   end
   objects = []
   output.each_line do |line|
      line.chomp!
      columns = line.split(/[[:blank:]]+/)
      objects.push(columns[0]) if !columns[0].empty?
   end
   
   return objects
end
master_netboot_kernel() click to toggle source

Pull the netboot_kernel attribute from NIM master object

# File lib/rbvppc/nim.rb, line 72
def master_netboot_kernel
   result = execute_cmd "lsnim -l master | awk '{if ($1 ~ /netboot_kernel/) print $3}'"
   return result.chomp
end
network_exists?(network_name,network_addr=nil) click to toggle source

Returns true if a network object exists on the NIM with either the specified name or network address. Returns false otherwise.

# File lib/rbvppc/nim.rb, line 423
def network_exists?(network_name,network_addr=nil)
   network_names = list_objtype("ent")
   if network_names.include?(network_name)
      return true
   end
   network_names.each do |net_name|
      address = execute_cmd("lsnim -l #{net_name} | awk '{if ($1 ~ /net_addr/) print $3}'").chomp
      if address == network_addr
         return true
      end
   end

   return false
end
remove_bid(client_lpar) click to toggle source

Remove the NIM BID object for a client LPAR

# File lib/rbvppc/nim.rb, line 339
def remove_bid(client_lpar)
   execute_cmd "nim -F -o remove #{client_lpar.name}_bid"
   #execute_cmd "nim -F -o remove #{client_lpar}_bid"
end
remove_client(client_lpar) click to toggle source

Remove a NIM client

# File lib/rbvppc/nim.rb, line 104
def remove_client(client_lpar)
   deallocate_resources(client_lpar)
   execute_cmd "nim -F -o remove #{client_lpar.name}"
end
remove_image(mksysb_name) click to toggle source

Removes a mksysb from the NIM that identifies with the name specified. Attempts to remove the SPOT that was extracted from this mksysb first.

# File lib/rbvppc/nim.rb, line 161
def remove_image(mksysb_name)
   #Find if this mksysb actually exists on the NIM
   images = list_images
   if !images.include?(mksysb_name)
      warn "#{mksysb_name} does not exist on this NIM."
      return
   end

   #Find and remove the SPOT for this mksysb
   spot_name = get_spot(mksysb_name)
   if !spot_name.nil?
      remove_spot(spot_name)
   end

   #Remove the mksysb from the NIM (along with it's mksysb file)
   execute_cmd("nim -o remove -a rm_image=yes #{mksysb_name}")
end
remove_network(network_name,network_addr=nil) click to toggle source

Remove a NIM network given it's name and/or it's network address

# File lib/rbvppc/nim.rb, line 412
def remove_network(network_name,network_addr=nil)
   #Ensure that the network to remove is actually defined currently
   raise StandardError.new("Network #{network_name} does not exist on this NIM to be removed") if !network_exists?(network_name,network_addr)
   
   #Run command that removes this network from the NIM
   execute_cmd("nim -Fo remove #{network_name}")
end
remove_spot(spot_name) click to toggle source

Removes a SPOT object from a NIM based on the name

# File lib/rbvppc/nim.rb, line 298
def remove_spot(spot_name)
   execute_cmd("nim -Fo remove #{spot_name}")
end
reset_client(client_lpar) click to toggle source

Reset a NIM client

# File lib/rbvppc/nim.rb, line 93
def reset_client(client_lpar)
    execute_cmd "nim -F -o reset #{client_lpar.name}"
    #execute_cmd "nim -F -o reset #{client_lpar}"
end