Class: OneDataAccessor

Inherits:
Object
  • Object
show all
Includes:
Errors, InputValidator
Defined in:
lib/one_data_accessor.rb

Overview

Class for accessing OpenNebula via XML RPC and requesting accounting data

Constant Summary collapse

STATE_DONE =
'6'

Constants included from InputValidator

InputValidator::NUMBER_RE, InputValidator::URI_RE

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from InputValidator

#is?, #is_number?, #is_uri?

Constructor Details

#initialize(compatibility, log = nil) ⇒ OneDataAccessor

Returns a new instance of OneDataAccessor.



21
22
23
24
25
26
27
28
29
30
31
# File 'lib/one_data_accessor.rb', line 21

def initialize(compatibility, log = nil)
  @log = log ? log : Logger.new(STDOUT)
  @compatibility = compatibility

  @batch_size = Settings.output['num_of_vms_per_file'] ? Settings.output['num_of_vms_per_file'] : 500
  fail ArgumentError, 'Wrong number of vms per file.' unless is_number?(@batch_size)

  @compatibility_vm_pool = nil

  initialize_client
end

Instance Attribute Details

#batch_sizeInteger (readonly)

number of vm records to request

Returns:

  • (Integer)

    the current value of batch_size



13
14
15
# File 'lib/one_data_accessor.rb', line 13

def batch_size
  @batch_size
end

#clientOpenNebula::Client (readonly)

client for communicaton with OpenNebula

Returns:

  • (OpenNebula::Client)

    the current value of client



13
14
15
# File 'lib/one_data_accessor.rb', line 13

def client
  @client
end

#compatibilityTrueClass, FalseClass (readonly)

whether or not communicate in compatibility mode (omit some newer API functions)

Returns:

  • (TrueClass, FalseClass)

    the current value of compatibility



13
14
15
# File 'lib/one_data_accessor.rb', line 13

def compatibility
  @compatibility
end

#logObject (readonly)

Returns the value of attribute log.



19
20
21
# File 'lib/one_data_accessor.rb', line 19

def log
  @log
end

#loggerany logger (readonly)

Returns the current value of logger.

Returns:

  • (any logger)

    the current value of logger



13
14
15
# File 'lib/one_data_accessor.rb', line 13

def logger
  @logger
end

Instance Method Details

#check_retval(rc, e_klass) ⇒ Object

Check OpenNebula return codes



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/one_data_accessor.rb', line 173

def check_retval(rc, e_klass)
  return true unless OpenNebula.is_error?(rc)
  case rc.errno
  when OpenNebula::Error::EAUTHENTICATION
    fail Errors::AuthenticationError, rc.message
  when OpenNebula::Error::EAUTHORIZATION
    fail Errors::UserNotAuthorizedError, rc.message
  when OpenNebula::Error::ENO_EXISTS
    fail Errors::ResourceNotFoundError, rc.message
  when OpenNebula::Error::EACTION
    fail Errors::ResourceStateError, rc.message
  else
    fail e_klass, rc.message
  end
end

#initialize_clientObject

Initialize OpenNebula client for further connection



34
35
36
37
38
39
40
# File 'lib/one_data_accessor.rb', line 34

def initialize_client
  secret = Settings['xml_rpc'] ? Settings.xml_rpc['secret'] : nil
  endpoint = Settings['xml_rpc'] ? Settings.xml_rpc['endpoint'] : nil
  fail ArgumentError, "#{endpoint} is not a valid URL." if endpoint && !is_uri?(endpoint)

  @client = OpenNebula::Client.new(secret, endpoint)
end

#load_vm_pool(batch_number) ⇒ Object

Load part of virtual machine pool

Parameters:

  • batch_number (Integer)


147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/one_data_accessor.rb', line 147

def load_vm_pool(batch_number)
  fail ArgumentError, "#{batch_number} is not a valid number" unless is_number?(batch_number)
  @log.debug("Loading vm pool with batch number: #{batch_number}.")
  from = batch_number * @batch_size
  to = (batch_number + 1) * @batch_size - 1

  #if in compatibility mode, whole virtual machine pool has to be loaded for the first time
  if @compatibility
    unless @compatibility_vm_pool
      vm_pool = OpenNebula::VirtualMachinePool.new(@client)
      rc = vm_pool.info(OpenNebula::Pool::INFO_ALL, -1, -1, OpenNebula::VirtualMachinePool::INFO_ALL_VM)
      check_retval(rc, Errors::ResourceRetrievalError)
      @compatibility_vm_pool = vm_pool.to_a
    end

    return @compatibility_vm_pool[from..to] || []
  else
    vm_pool = OpenNebula::VirtualMachinePool.new(@client)
    rc = vm_pool.info(OpenNebula::Pool::INFO_ALL, from, to, OpenNebula::VirtualMachinePool::INFO_ALL_VM)
    check_retval(rc, Errors::ResourceRetrievalError)

    return vm_pool
  end
end

#mapping(pool_class, xpath) ⇒ Hash

Create mapping from element's ID to its xpath value

Parameters:

  • pool_class (one of OpenNebula pool classes)

    pool to read elements from

  • xpath (String)

    xpath pointing to value within the element

Returns:

  • (Hash)

    generated map



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/one_data_accessor.rb', line 48

def mapping(pool_class, xpath)
  @log.debug("Generating mapping for class: #{pool_class} and xpath: '#{xpath}'.")
  pool = pool_class.new(@client)
  #call info_all method instead of info on pools that support it
  if pool.respond_to? 'info_all'
    rc = pool.info_all
    check_retval(rc, Errors::ResourceRetrievalError)
  else
    rc = pool.info
    check_retval(rc, Errors::ResourceRetrievalError)
  end

  #generate mapping
  map = {}
  pool.each do |item|
    unless item['ID']
      @log.error("Skipping a resource of the type #{pool_class} without an ID present.")
      next
    end
    map[item['ID']] = item[xpath]
  end

  map
end

#vm(vm_id) ⇒ OpenNebula::VirtualMachine

Retrieve virtual machine

Parameters:

  • vm_id (Integer)

    ID of vm to retrieve

Returns:

  • (OpenNebula::VirtualMachine)

    virtual machine



78
79
80
81
82
83
84
85
# File 'lib/one_data_accessor.rb', line 78

def vm(vm_id)
  fail ArgumentError, "#{vm_id} is not a valid id." unless is_number?(vm_id)
  @log.debug("Retrieving virtual machine with id: #{vm_id}.")
  vm = OpenNebula::VirtualMachine.new(OpenNebula::VirtualMachine.build_xml(vm_id), @client)
  rc = vm.info
  check_retval(rc, Errors::ResourceRetrievalError)
  vm
end

#vms(batch_number, range, groups) ⇒ Array

Retriev IDs of specified virtual machines

Parameters:

  • batch_number (Integer)
  • range (Hash)

    date range into which virtual machine has to belong

  • groups (Hash)

    groups into one of which owner of the virtual machine has to belong

Returns:

  • (Array)

    array with virtual machines' IDs



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/one_data_accessor.rb', line 94

def vms(batch_number, range, groups)
  vms = []
  #load specific batch
  vm_pool = load_vm_pool(batch_number)
  return nil if vm_pool.count == 0

  @log.debug("Searching for vms based on range: #{range} and groups: #{groups}.")
  vm_pool.each do |vm|
    unless vm['ID']
      @log.error('Skipping a record without an ID present.')
      next
    end

    #skip unsuitable virtual machines
    next unless want?(vm, range, groups)

    vms << vm['ID'].to_i
  end

  @log.debug("Selected vms: #{vms}.")
  vms
end

#want?(vm, range, groups) ⇒ TrueClass, FalseClass

Check whether obtained vm meets requierements

Parameters:

  • vm (OpenNebula::VirtualMachine)

    virtual machine instance to check

  • range (Hash)

    date range into which virtual machine has to belong

  • groups (Hash)

    groups into one of which owner of the virtual machine has to belong

Returns:

  • (TrueClass, FalseClass)

    true if virtual machine meets requirements, false otherwise



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

def want?(vm, range, groups)
  if vm.nil?
    @log.warn('Obtained nil vm from vm pool.')
    return false
  end
  # range restriction
  unless range.nil? || range.empty?
    return false if range[:from] && vm['STATE'] == STATE_DONE && vm['ETIME'].to_i < range[:from].to_i
    return false if range[:to] && vm['STIME'].to_i > range[:to].to_i
  end

  # groups restriction
  unless groups.nil? || groups.empty?
    return false if groups[:include] && !groups[:include].include?(vm['GNAME'])
    return false if groups[:exclude] && groups[:exclude].include?(vm['GNAME'])
  end

  true
end