Home > System Administration > Delaying VM Deletion during Retirement in CFME 5.4

Delaying VM Deletion during Retirement in CFME 5.4

September 29th, 2015 Leave a comment Go to comments

At $DAYJOB we would like to be able to “un-retire” a VM, especially in those cases where a customer retires it and “didn’t know that’s what it would do” or similar. To meet these requirements, I’ve introduced a delay in processing the full retirement by overriding the default pre_retirement.rb method. Here’s the gist of things:

#
# Description: This method powers-off the VM on the provider and waits for Retirement Delay to pass before continuing
#
 
require 'miq_dev_util'
 
@logger = MiqDevUtil::Logger.new($evm, 'pre_retirement')
 
vm = $evm.root['vm']
customer_id = $evm.instantiate('/Configuration/Methods/get_customer_identifier')['return_value']
retirement_delay = $evm.instantiate("/Infrastructure/VM/Retirement/Configuration/RetirementDelay/#{customer_id}")['retirement_delay'].gsub(' ', '.')
 
#TODO: Figure out a way to ensure retirement_delay is valid
 
@logger.log('info', "Found Customer #{customer_id} with retirement delay #{retirement_delay}")
 
# Power off the VM
unless vm.nil? || vm.attributes['power_state'] == 'off'
  ems = vm.ext_management_system
  @logger.log('info', "Powering Off VM <#{vm.name}> in provider <#{ems.try(:name)}>")
  vm.stop
end
 
# If we don't have a delay, continue on
if retirement_delay.nil?
  @logger.log('info', "No retirement delay requested. Continuing with the process")
 
# Otherwise process the delay
else
  if vm.retirement_state == 'retiring'
    @logger.log('info', "Delaying #{retirement_delay} before finishing retirement for #{vm.name}")
    # The VM isn't really retired here, but for display purposes lets see what happens
    # The retirement date isn't set, so that may be a way to differentiate if we need to
    vm['retired'] = true # Because exposing the retired= method is too hard?
    vm.retirement_state = 'delaying'
    $evm.root['ae_result']         = 'retry'
    $evm.root['ae_retry_interval'] = "#{retirement_delay}"
  elsif vm.retirement_state == 'delaying'
    @logger.log('info', "Retirement delay reached. Continuing with the process.")
    vm['retired'] = false # Have to set this back so finish_retirement doesn't bomb later.
    vm.retirement_state = 'retiring'
  end
end

Some items of note:

  1. I’m using the miq_dev_util module written by my colleague that provides a couple of nice utility functions. In this case I’m only using the logging, so swapping that out would be no big deal.
  2. The VM gets “retired” very early on so that the VM shows up with an ‘R’ for an icon and it is obvious it’s been retired – even though it hasn’t been deleted. During this time, the Retirement Status is set to “Delaying”.
  3. We take advantage of the retry capabilities of the state machine to perform the delay for us.
  4. customer_identifier is something internal to us. You can use whatever key you like to search for the appropriate instance of RetirementDelay. Eventually, retirement_delay should contain a ruby-valid time statement, such as ’60.minutes’ or ‘7.days’

Hope you find this useful!