Class: VcenterLibMongodb::Mongodb

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/vcenter_lib_mongodb/mongodb.rb

Overview

access vms and their facts from mongo database

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Logging

included, #logger, #logger=

Constructor Details

#initialize(connection, vms = :vms, meta = :meta) ⇒ Mongodb

initialize access to mongodb

You might want to adjust the logging level, for example:

::Mongo::Logger.logger.level = logger.level

Parameters:

  • connection

    mongodb connection, should already be switched to correct database

  • vms (defaults to: :vms)

    symbol for collection that contains vms with their facts

  • meta (defaults to: :meta)

    symbol for collection with update metadata



22
23
24
25
26
27
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 22

def initialize(connection, vms = :vms, meta = :meta)
  @connection = connection
  @vms_collection = vms
  @meta_collection = meta
  @convert = ::PuppetDBQuery::ToMongo.new
end

Instance Attribute Details

#connectionObject (readonly)

Returns the value of attribute connection.



9
10
11
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 9

def connection
  @connection
end

#convertObject (readonly)

Returns the value of attribute convert.



12
13
14
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 12

def convert
  @convert
end

#meta_collectionObject (readonly)

Returns the value of attribute meta_collection.



11
12
13
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 11

def meta_collection
  @meta_collection
end

#vms_collectionObject (readonly)

Returns the value of attribute vms_collection.



10
11
12
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 10

def vms_collection
  @vms_collection
end

Instance Method Details

#all_vmsObject

get all vm names



30
31
32
33
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 30

def all_vms
  collection = connection[vms_collection]
  collection.find.batch_size(999).projection(_id: 1).map { |k| k[:_id] }
end

#facts(facts = []) ⇒ Object

get all vms and their facts

Parameters:

  • facts (Array<String>) (defaults to: [])

    get these facts in the result, eg [‘fqdn’], empty for all



125
126
127
128
129
130
131
132
133
134
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 125

def facts(facts = [])
  fields = Hash[facts.collect { |fact| [fact.to_sym, 1] }]
  collection = connection[vms_collection]
  result = {}
  collection.find.batch_size(999).projection(fields).each do |values|
    id = values.delete('_id')
    result[id] = values
  end
  result
end

#metaObject

get meta informations about updates



137
138
139
140
141
142
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 137

def meta
  collection = connection[meta_collection]
  result = collection.find.first
  result.delete(:_id)
  result
end

#meta_fact_update(method, ts_begin, ts_end) ⇒ Object

update or insert timestamps for given fact update method



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 185

def meta_fact_update(method, ts_begin, ts_end)
  connection[meta_collection].find_one_and_update(
    {},
    {
      '$set' => {
        last_fact_update: {
          ts_begin: ts_begin.iso8601,
          ts_end:   ts_end.iso8601,
          method:   method
        },
        method => {
          ts_begin: ts_begin.iso8601,
          ts_end:   ts_end.iso8601
        }
      }
    },
    { upsert: true }
  )
end

#query_facts(query, facts = []) ⇒ Hash<name, <fact , value>>

get vms and their facts that fulfill given mongodb query

Parameters:

  • query (String)

    a query for VMs

  • facts (Array<String>) (defaults to: [])

    get these facts in the result, eg [‘boot_time’], empty for all

Returns:

  • (Hash<name, <fact , value>>)

    VM names with their facts and values



52
53
54
55
56
57
58
59
60
61
62
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 52

def query_facts(query, facts = [])
  mongo_query = convert.query(query)
  fields = Hash[facts.collect { |fact| [fact.to_sym, 1] }]
  collection = connection[vms_collection]
  result = {}
  collection.find(mongo_query).batch_size(999).projection(fields).each do |values|
    id = values.delete('_id')
    result[id] = values
  end
  result
end

#query_facts_exist(query, facts = []) ⇒ Object

get vms and their facts that fulfill given mongodb query and have at least one value for one the given fact names

Parameters:

  • query

    mongodb query

  • facts (Array<String>) (defaults to: [])

    get these facts in the result, eg [‘fqdn’], empty for all



69
70
71
72
73
74
75
76
77
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 69

def query_facts_exist(query, facts = [])
  result = query_facts(query, facts)
  unless facts.empty?
    result.keep_if do |_k, v|
      facts.any? { |f| !v[f].nil? }
    end
  end
  result
end

#query_vms(query) ⇒ Array<String>

get vm names that fulfill given query

Parameters:

  • query (String)

    a query for VMs. nil or white space only string will return all VMs

Returns:

  • (Array<String>)

    names of VMs that fulfill the query



40
41
42
43
44
45
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 40

def query_vms(query)
  return all_vms if query.nil? || query.strip.empty?
  mongo_query = convert.query(query)
  collection = connection[vms_collection]
  collection.find(mongo_query).batch_size(999).projection(_id: 1).map { |k| k[:_id] }
end

#search_facts(query, pattern, facts = [], facts_found = [], check_names = false) ⇒ Object

get VMs and their facts for a pattern

Parameters:

  • query

    mongodb query

  • pattern (RegExp)

    search for

  • facts (Array<String>) (defaults to: [])

    get these facts in the result, eg [‘fqdn’], empty for all

  • facts_found (Array<String>) (defaults to: [])

    fact names are added to this array

  • check_names (Boolean) (defaults to: false)

    also search fact names



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 86

def search_facts(query, pattern, facts = [], facts_found = [], check_names = false)
  mongo_query = convert.query(query)
  collection = connection[vms_collection]
  result = {}
  collection.find(mongo_query).batch_size(999).each do |values|
    id = values.delete('_id')
    found = {}
    values.each do |k, v|
      if v =~ pattern
        found[k] = v
      elsif check_names && k =~ pattern
        found[k] = v
      end
    end
    next if found.empty?
    facts_found.concat(found.keys).uniq!
    facts.each do |f|
      found[f] = values[f]
    end
    result[id] = found
  end
  result
end

#single_vm_facts(vm, facts) ⇒ Object

get facts for given vm name

Parameters:

  • vm (String)

    vm name

  • facts (Array<String>)

    get these facts in the result, eg [‘fqdn’], empty for all



114
115
116
117
118
119
120
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 114

def single_vm_facts(vm, facts)
  fields = Hash[facts.collect { |fact| [fact.to_sym, 1] }]
  collection = connection[vms_collection]
  result = collection.find(_id: vm).limit(1).batch_size(1).projection(fields).to_a.first
  result.delete("_id") if result
  result
end

#vm_delete(vm) ⇒ Object

delete vm data for given vm name

Parameters:

  • vm (String)

    vm name



180
181
182
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 180

def vm_delete(vm)
  connection[vms_collection].find(_id: vm).delete_one
end

#vm_update(vm, facts) ⇒ Object

update or insert facts for given vm name

Parameters:

  • vm (String)

    vm name

  • facts (Hash)

    facts for the vm



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/vcenter_lib_mongodb/mongodb.rb', line 148

def vm_update(vm, facts)
  logger.debug "  updating #{vm}"
  connection[vms_collection].find(_id: vm).replace_one(facts,
    upsert:                     true,
    bypass_document_validation: true,
    check_keys:                 false,
    validating_keys:            false)
rescue ::Mongo::Error::OperationFailure => e
  logger.warn "  updating #{vm} failed with: #{e.message}"
  # mongodb doesn't support keys with a dot
  # see https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names
  # as a dirty workaround we delete the document and insert it ;-)
  # The dotted field .. in .. is not valid for storage. (57)
  # .. is an illegal key in MongoDB. Keys may not start with '$' or contain a '.'.
  # (BSON::String::IllegalKey)
  raise e unless e.message =~ /The dotted field / || e.message =~ /is an illegal key/
  logger.warn "    we transform the dots into underline characters"
  begin
    facts = Hash[facts.map { |k, v| [k.tr('.', '_'), v] }]
    connection[vms_collection].find(_id: vm).replace_one(facts,
      upsert: true,
      bypass_document_validation: true,
      check_keys: false,
      validating_keys: false)
  rescue
    logger.error "  inserting #{vm} failed again with: #{e.message}"
  end
end