Class: Dcmgr::Models::Instance

Inherits:
AccountResource show all
Defined in:
lib/dcmgr/models/instance.rb

Overview

Model class which represents Virtual Machine or Isolated Instace running on HostPool.

Defined Under Namespace

Modules: ValidationMethods

Constant Summary

Constants inherited from BaseNew

BaseNew::LOCK_TABLES_KEY

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from AccountResource

#account

Methods inherited from BaseNew

Proxy, dataset, install_data, install_data_hooks, unlock!

Class Method Details

.lock!Object



330
331
332
333
334
335
336
337
338
# File 'lib/dcmgr/models/instance.rb', line 330

def self.lock!
  super()
  Image.lock!
  InstanceSpec.lock!
  InstanceNic.lock!
  Volume.lock!
  VolumeSnapshot.lock!
  IpLease.lock!
end

Instance Method Details

#_deleteObject

override Sequel::Model#_delete not to delete rows but to set delete flags.



146
147
148
149
150
151
# File 'lib/dcmgr/models/instance.rb', line 146

def _delete
  self.terminated_at ||= Time.now
  self.state = :terminated if self.state != :terminated
  self.status = :offline if self.status != :offline
  self.save
end

#add_nic(network, vendor_id = nil) ⇒ Object



259
260
261
262
263
264
265
266
# File 'lib/dcmgr/models/instance.rb', line 259

def add_nic(network, vendor_id=nil)
  # TODO: get default vendor ID based on the hypervisor.
  vendor_id ||= '00:ff:f1'
  nic = InstanceNic.new(:mac_addr=>vendor_id)
  nic.network = network
  nic.instance = self
  nic.save
end

#archObject

Returns the architecture type of the image



243
244
245
# File 'lib/dcmgr/models/instance.rb', line 243

def arch
  self.image.arch
end

#before_destroyObject



132
133
134
135
136
137
138
139
140
141
142
# File 'lib/dcmgr/models/instance.rb', line 132

def before_destroy
  HostnameLease.filter(:account_id=>self., :hostname=>self.hostname).destroy
  self.instance_nic.each { |o| o.destroy }
  self.instance_netfilter_groups.each{|o| o.destroy }
  self.volume.each { |v|
    v.instance_id = nil
    v.state = :available
    v.save
  }
  super
end

#before_saveObject



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/dcmgr/models/instance.rb', line 110

def before_save
  if @update_hostname
    if new?
      HostnameLease.create(:account_id=>self.,
                           :hostname=>self.hostname)
    else
      orig = self.dup.refresh
      # do nothing if orig.hostname == self.hostname
      if orig.hostname != self.hostname
        
        orig_name = HostnameLease.filter(:account_id=>self.,
                                         :hostname=>orig.hostname).first
        orig_name.hostname = self.hostname
        orig_name.save
      end
    end
    @update_hostname = false
  end
  
  super
end

#before_validationObject



103
104
105
106
107
108
# File 'lib/dcmgr/models/instance.rb', line 103

def before_validation
  self[:user_data] ||= ''
  self[:hostname] ||= self.uuid
  self[:hostname] = self[:hostname].downcase
  super
end

#configObject



255
256
257
# File 'lib/dcmgr/models/instance.rb', line 255

def config
  self.instance_spec.config
end

#cpu_coresObject



247
248
249
# File 'lib/dcmgr/models/instance.rb', line 247

def cpu_cores
  self.instance_spec.cpu_cores
end

#fqdn_hostnameObject

def netfilter_group_instances

  instances = self.netfilter_groups.map { |g| g.instances }

  instances.flatten!.uniq! if instances.size > 0
  instances
end


297
298
299
# File 'lib/dcmgr/models/instance.rb', line 297

def fqdn_hostname
  sprintf("%s.%s.%s", self.hostname, self..uuid, self.nic.first.network.domain_name)
end

#hypervisorObject

Returns the hypervisor type for the instance.



238
239
240
# File 'lib/dcmgr/models/instance.rb', line 238

def hypervisor
  self.host_pool.hypervisor
end

#ipsObject



286
287
288
# File 'lib/dcmgr/models/instance.rb', line 286

def ips
  self.instance_nic.map { |nic| nic.ip }
end

#join_netfilter_group(netfilter_group_uuids) ⇒ Object

Join this instance to the list of netfilter group using group’s uuid.

Parameters:

  • netfilter_group_uuids (String, Array)


270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/dcmgr/models/instance.rb', line 270

def join_netfilter_group(netfilter_group_uuids)
  netfilter_group_uuids = [netfilter_group_uuids] if netfilter_group_uuids.is_a?(String)
  joined_group_uuids = self.netfilter_groups.map { |netfilter_group|
    netfilter_group.canonical_uuid
  }
  target_group_uuids = netfilter_group_uuids.uniq - joined_group_uuids.uniq
  target_group_uuids.uniq!

  target_group_uuids.map { |target_group_uuid|
    if ng = NetfilterGroup[target_group_uuid]
      InstanceNetfilterGroup.create(:instance_id => self.id,
                                    :netfilter_group_id => ng.id)
    end
  }
end

#join_nfgroup_by_name(account_id, nfgroup_names) ⇒ Object

Join this instance to the list of netfilter group using group name.

Parameters:

  • account_id (String)

    uuid of current account.

  • nfgroup_names (String, Array)


318
319
320
321
322
323
324
325
326
327
328
# File 'lib/dcmgr/models/instance.rb', line 318

def join_nfgroup_by_name(, nfgroup_names)
  nfgroup_names = [nfgroup_names] if nfgroup_names.is_a?(String)

  uuids = nfgroup_names.map { |n|
    ng = NetfilterGroup.for_update.filter(:account_id=>,
                                          :name=>n).first
    ng.nil? ? nil : ng.canonical_uuid
  }
  # clean up nils
  join_netfilter_group(uuids.compact.uniq)
end

#live?Boolean

Returns:

  • (Boolean)


340
341
342
# File 'lib/dcmgr/models/instance.rb', line 340

def live?
  self.terminated_at.nil?
end

#memory_sizeObject



251
252
253
# File 'lib/dcmgr/models/instance.rb', line 251

def memory_size
  self.instance_spec.memory_size
end

#networksArray[Models::Network]

Retrieve all networks belong to this instance

Returns:



303
304
305
306
307
308
309
310
311
312
313
# File 'lib/dcmgr/models/instance.rb', line 303

def networks
  instance_nic.select { |nic|
    !nic.ip.nil?
  }.map { |nic|
    nic.ip.network
  }.group_by { |net|
    net.canonical_uuid
  }.values.map { |i|
    i.first
  }
end

#to_api_documentObject

returns hash data for API response on GET instances/

{ :id=>

:cpu_cores
:memory_size
:image_id
:network => [{:network_name=>'nw-xxxxxxx', :ipaddr=>'111.111.111.111'}]
:volume => [{'uuid'=>{:guest_device_name=>,}]
:ssh_key_pair => 'xxxxx',
:netfilter_group => ['rule1', 'rule2']
:created_at
:state
:status

}



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/dcmgr/models/instance.rb', line 190

def to_api_document
  h = {
    :id => canonical_uuid,
    :cpu_cores   => instance_spec.cpu_cores,
    :memory_size => instance_spec.memory_size,
    :image_id    => image.canonical_uuid,
    :created_at  => self.created_at,
    :state => self.state,
    :status => self.status,
    :ssh_key_pair => nil,
    :network => [],
    :volume => [],
    :netfilter_group => [],
  }
  if self.ssh_key_pair
    h[:ssh_key_pair] = self.ssh_key_pair.name
  end

  if instance_nic
    instance_nic.each { |n|
      if n.ip
        h[:network] << {
          :network_name => n.network.canonical_uuid,
          :ipaddr => n.ip.ipv4
        }
      end
    }
  end
  
  if self.volume
    self.volume.each { |v|
      h[:volume] << {
        :vol_id => v.canonical_uuid,
        :guest_device_name=>v.guest_device_name,
        :state=>v.state,
      }
    }
  end

  if self.netfilter_groups
    self.netfilter_groups.each { |n|
      h[:netfilter_group] << n.name
    }
  end
  h
end

#to_hashObject

dump column data as hash with details of associated models. this is for internal use.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/dcmgr/models/instance.rb', line 155

def to_hash
  h = super
  h = h.merge({:user_data => user_data.to_s, # Sequel::BLOB -> String
                :runtime_config => self.runtime_config, # yaml -> hash
                :image=>image.to_hash,
                :host_pool=>host_pool.to_hash,
                :instance_nics=>instance_nic.map {|n| n.to_hash },
                :instance_spec=>instance_spec.to_hash,
                :ips => instance_nic.map { |n| n.ip.ipv4 if n.ip },
              })
  h[:volume]={}
  if self.volume
    self.volume.each { |v|
      h[:volume][v.canonical_uuid] = v.to_hash
    }
  end
  h
end

#validateObject



61
62
63
64
65
66
67
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
# File 'lib/dcmgr/models/instance.rb', line 61

def validate
  super

  unless self.hostname =~ /\A[0-9a-z][0-9a-z\-]{0,31}\Z/
    errors.add(:hostname, "Invalid hostname syntax")
  end

  # uniqueness check for hostname
  if changed_columns.include?(:hostname)
    proc_test = lambda {
      unless ValidationMethods.hostname_uniqueness(self., self.hostname)
        errors.add(:hostname, "Duplicated hostname: #{self.hostname}")
      end
    }
    
    if new?
      proc_test.call
    else
      orig = self.dup.refresh
      # do nothing if orig.hostname == self.hostname
      if orig.hostname != self.hostname
        proc_test.call
      end
    end
    @update_hostname = true
  end
  
  # check runtime_config column
  case self.hypervisor
  when HostPool::HYPERVISOR_KVM
    r1 = self.runtime_config
    self.host_pool.instances.each { |i|
      next true if i.id == self.id
      r2 = i.runtime_config
      unless r1[:vnc_port] != r2[:vnc_port] && r1[:telnet_port] != r2[:telnet_port]
        errors.add(:runtime_config, "#{self.canonical_uuid}.runtime_config conflicted with #{i.canonical_uuid}")
        break
      end
    }
  end
end