Class: LeaseTool

Inherits:
Object
  • Object
show all
Defined in:
lib/rbvmomi/utils/leases.rb

Overview

A class to manage VM leases

This class uses YAML encoded VM annotations (config.annotation) to manage a lease system. It helps add such lease info onto new and existing VMs and to find VMs that have expired leases or that are about to have expired leases. The calling code can use those to generate emails with about-to-expire notifications, suspend, power off or destroy VMs that have exceeded their lease, etc.

Instance Method Summary collapse

Instance Method Details

#current_timeTime

Retrieve the current time as used by the lease tool.

Returns:

  • (Time)

    Current time as used by the lease tool



38
39
40
41
# File 'lib/rbvmomi/utils/leases.rb', line 38

def current_time
  # XXX: Should swith to time provided by VC
  Time.now
end

#filter_expired_vms(vms, vmprops, opts = {}) ⇒ Array

Filter the list of passed in Virtul Machines and find the one that are expired. A time offset can be used to identify VMs that will expire at a certain point in the future. If a VM doesn’t have a lease, it is treated as never expiring.

Parameters:

  • vms (Array)

    List of VIM::VirtualMachine instances, may or may not have leases

  • vmprops (Hash)

    Hash of VIM::VirtualMachine instances to their properties

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • :time_delta (int)

    Time delta (seconds) to be added to current time

Returns:

  • (Array)

    List of expired VMs



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/rbvmomi/utils/leases.rb', line 125

def filter_expired_vms vms, vmprops, opts = {}
  time_delta = opts[:time_delta] || 0
  time = current_time + time_delta

  out = vms.map do |vm|
    props = vmprops[vm]
    next unless annotation = props['config.annotation']

    note = YAML.load annotation
    next unless note.is_a?(Hash) && lease = note['lease']
    next unless time > lease

    time_to_expiration = ((lease - time) + time_delta)
    [vm, time_to_expiration]
  end.compact
  out = Hash[out]
  out
end

#find_leaseless_vms(vms, vmprops) ⇒ Array

Filter the list of passed in Virtual Machines and find the ones that currently do not have a lease.

Parameters:

  • vms (Array)

    List of VIM::VirtualMachine instances, may or may not have leases

  • vmprops (Hash)

    Hash of VIM::VirtualMachine instances to their properties

Returns:

  • (Array)

    List of leaseless VMs



106
107
108
109
110
111
112
113
114
115
# File 'lib/rbvmomi/utils/leases.rb', line 106

def find_leaseless_vms vms, vmprops
  vms.reject do |vm|
    props = vmprops[vm]
    annotation = props['config.annotation']
    if annotation
      note = YAML.load annotation
      note.is_a?(Hash) && note['lease']
    end
  end
end

#get_vms_props(vms) ⇒ Hash

Fetch all VM properties that the LeaseTool needs on all VMs passed in.

Parameters:

  • vms (Array)

    List of VIM::VirtualMachine instances

Returns:

  • (Hash)

    Hash of VMs as keys and their properties as values



27
28
29
30
31
32
33
34
# File 'lib/rbvmomi/utils/leases.rb', line 27

def get_vms_props vms
  out = {}
  if vms.length > 0
    pc = vms.first._connection.serviceContent.propertyCollector
    out = pc.collectMultiple(vms, 'name', 'config.annotation')
  end
  out
end

#set_lease_in_vm_config(vmconfig, lease_minutes) ⇒ Hash

Helper function that sets the lease info in a passed in VM config. If there is no annotation, it is added. If there is an annotation, it is updated to include the lease info. Note that if the annotation isn’t YAML, it is overwritten.

Parameters:

  • vmconfig (Hash)

    Virtual Machine config spec

  • lease_minutes (int)

    Time to lease expiration from now in minutes

Returns:

  • (Hash)

    Updated Virtual Machine config spec



50
51
52
53
54
55
56
57
58
59
# File 'lib/rbvmomi/utils/leases.rb', line 50

def set_lease_in_vm_config vmconfig, lease_minutes
  annotation = vmconfig[:annotation]
  annotation ||= ''
  note = YAML.load annotation
  note = {} if !note.is_a?(Hash)
  lease = current_time + lease_minutes * 60
  note['lease'] = lease
  vmconfig[:annotation] = YAML.dump(note)
  vmconfig
end

#set_lease_on_leaseless_vms(vms, vmprops, opts = {}) ⇒ Array

Issue ReconfigVM_Task to set the lease on all VMs that currently do not have a lease. All VM reconfigurations are done in parallel and the function waits for all of them to complete

Parameters:

  • vms (Array)

    List of VIM::VirtualMachine instances, may or may not have leases

  • vmprops (Hash)

    Hash of VIM::VirtualMachine instances to their properties

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • :lease_minutes (int)

    Time to lease expiration from now in minutes

Returns:

  • (Array)

    List of previously leaseless VMs that now have a lease



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/rbvmomi/utils/leases.rb', line 84

def set_lease_on_leaseless_vms vms, vmprops, opts = {}
  lease_minutes = opts[:lease_minutes]
  raise 'Expected lease_minutes to be specified' if !lease_minutes

  vms = find_leaseless_vms vms, vmprops
  if vms.length > 0
    tasks = vms.map do |vm|
      annotation = vmprops[vm]['config.annotation']
      task = set_lease_on_vm_task(vm, lease_minutes, annotation)
      task
    end
    si = vms.first._connection.serviceInstance
    si.wait_for_multiple_tasks [], tasks
  end
  vms
end

#set_lease_on_vm_task(vm, lease_minutes, annotation = nil) ⇒ VIM::Task

Issue ReconfigVM_Task on the VM to update the lease. User can pass in current annotation, but if not, it is retrieved on demand. A task is returned, i.e. function doesn’t wait for completion.

Parameters:

  • vm (VIM::VirtualMachine)

    Virtual Machine instance

  • lease_minutes (int)

    Time to lease expiration from now in minutes

  • annotation (String) (defaults to: nil)

    ‘config.annotation’ property of the VM. Optional.

Returns:

  • (VIM::Task)

    VM reconfiguration task



68
69
70
71
72
73
74
75
# File 'lib/rbvmomi/utils/leases.rb', line 68

def set_lease_on_vm_task vm, lease_minutes, annotation = nil
  annotation = vm.collect 'config.annotation' if !annotation
  vmconfig = {annotation: annotation}
  vmconfig = set_lease_in_vm_config vmconfig, lease_minutes
  # XXX: It may be a good idea to cite the VM version here to avoid
  #      concurrent writes to the annotation stepping on each others toes
  vm.ReconfigVM_Task(spec: vmconfig)
end

#vms_props_listArray

Lists of VM properties the LeaseTool needs to do its job. Can be used to construct larger property collector calls that retrieve more info than just one subsystem needs.

Returns:

  • (Array)

    List of property names



20
21
22
# File 'lib/rbvmomi/utils/leases.rb', line 20

def vms_props_list
  ['name', 'config.annotation']
end