Class: OpenNebula::TrafficRecords

Inherits:
RecordsSource show all
Defined in:
service/records/traffic_records.rb

Overview

(Traffic)Records source class for fullfilling Timeline

Instance Attribute Summary

Attributes inherited from RecordsSource

#id

Instance Method Summary collapse

Methods inherited from RecordsSource

check_source, #records, tl_filter

Constructor Details

#initialize(id, nosync = false) ⇒ TrafficRecords

inits RecordsSource class with TrafficRecord class as base and syncronysing frequency and records(unless no nosync given)



61
62
63
64
65
# File 'service/records/traffic_records.rb', line 61

def initialize id, nosync = false
  super(TrafficRecord, id)
  @bill_freq = IONe::Settings['TRAFFIC_BILL_FREQ']
  sync unless nosync
end

Instance Method Details

#find(st, et) ⇒ Object

Find records between given time and make new active record if last one is bigger than 24h



130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'service/records/traffic_records.rb', line 130

def find st, et
  last = TrafficRecord.where(vm: @id).order(Sequel.asc(:stime)).last
  return EmptyQuery.new if last.nil? # EmptyQuerySet for Biller

  if last[:etime] - last[:stime] >= @bill_freq then # If record is elder than 24 hours
    args = last.values.without(:key, :rx, :tx, :stime)
    args.merge! rx: 0, tx: 0, stime: args[:etime] # Setting up new record with zero rx, tx and same rx_last, tx_last
    TrafficRecord.insert(**args)
  end

  # All Records between given time and elder than 24h
  @records.exclude(etime: nil).exclude(Sequel.lit('etime - stime < ?', @bill_freq)).where(etime: st..et)
end

#init_state(stime) ⇒ Object

Gets last traffic record, if there's no, then returns 0,0 for in- and outbound. Otherwise gets data from last record



145
146
147
148
149
150
151
152
153
# File 'service/records/traffic_records.rb', line 145

def init_state stime
  state = { rx: 0, tx: 0 }
  rec = TrafficRecord.where(vm: @id).where(etime: stime).all.last
  unless rec.nil? then
    rec = rec.to_i
    state[:rx], state[:tx] = rec.rx, rec.tx
  end
  state
end

#keyObject

Overrides key for db queries



56
57
58
# File 'service/records/traffic_records.rb', line 56

def key
  :vm
end

#next?(ts, last) ⇒ Boolean

Filter expression

Returns:

  • (Boolean)


83
84
85
# File 'service/records/traffic_records.rb', line 83

def next? ts, last # Filter expression
  return !last[:etime].nil? && ts <= last[:etime] # If TrafficRecord is already finished or new record is elder then last update
end

#sync(vm = nil) ⇒ Object

Update TrafficRecords with VM monitoring data



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'service/records/traffic_records.rb', line 68

def sync vm = nil
  if vm.nil? then
    vm = onblock :vm, @id
    vm.info!
  end

  last = TrafficRecord.where(vm: vm.id).order(Sequel.asc(:stime)).last # Get last Trafficrecord
  if last.nil? then # Give up if nil
    TrafficRecord.insert(
      vm: @id, rx: "0", tx: "0", rx_last: "0", tx_last: "0", stime: 0, etime: 0
    )
    last = TrafficRecord.where(vm: vm.id).order(Sequel.asc(:stime)).last # Get last Trafficrecord
  end
  last = last.to_i # @see TrafficRecord#to_i

  def next? ts, last # Filter expression
    return !last[:etime].nil? && ts <= last[:etime] # If TrafficRecord is already finished or new record is elder then last update
  end

  # Next block does generate hash structure like { timestamp => {rx, tx} }
  mon_raw = vm.monitoring(['NETTX', 'NETRX'])
  return 0 if OpenNebula.is_error? mon_raw

  mon = {}
  mon_raw['NETTX'].each do | el |
    el[0] = el[0].to_i
    next if next? el.first, last # Filter records which have been counted

    mon[el.first] = {}
    mon[el.first][:tx] = el.last
  end
  mon_raw['NETRX'].each do | el |
    el[0] = el[0].to_i
    next if next? el.first, last # Filter records which have been counted

    mon[el.first][:rx] = el.last
  end

  return 0 if mon.keys.size == 0 # drop if all of the monitoring records has been skipped

  for ts, data in mon do # Writing new data to active record
    data[:rx], data[:tx] = data[:rx].to_i, data[:tx].to_i
    last = last.to_i

    if last[:rx_last] > data[:rx] || last[:tx_last] > data[:tx] then
      last[:rx] += data[:rx]
      last[:tx] += data[:tx]
    else
      last[:rx] += (data[:rx] - last[:rx_last])
      last[:tx] += (data[:tx] - last[:tx_last])
    end

    last[:rx_last], last[:tx_last] = data[:rx], data[:tx]
    last[:etime] = ts
  end

  TrafficRecord.where(stime: last[:stime]).update(**last.values.without(:key)) # Write down updated data

  mon.keys.size # Just for logs
end