wakame-vdc-agents 10.11.0 → 10.12.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -45,6 +45,10 @@ module Dcmgr
45
45
  define_error(:OutOfHostCapacity, 400)
46
46
  define_error(:UnknownSshKeyPair, 404)
47
47
  define_error(:UndefinedStoragePoolID, 400)
48
+ define_error(:DetachVolumeFailure, 400)
49
+ define_error(:AttachVolumeFailure, 400)
50
+ define_error(:InvalidInstanceState, 400)
51
+ define_error(:DuplicateHostname, 400)
48
52
 
49
53
  # netfilter_group
50
54
  define_error(:UndefinedNetfilterGroup, 400)
@@ -0,0 +1,79 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'eventmachine'
4
+ require 'shellwords'
5
+ raise "Shellword is old version." unless Shellwords.respond_to?(:shellescape)
6
+ require 'open4'
7
+
8
+ module Dcmgr
9
+ module Helpers
10
+ module CliHelper
11
+ class TimeoutError < RuntimeError; end
12
+
13
+ def tryagain(opts={:timeout=>60, :retry=>3}, &blk)
14
+ timedout = false
15
+ curthread = Thread.current
16
+
17
+ timersig = EventMachine.add_timer(opts[:timeout]) {
18
+ timedout = true
19
+ if curthread
20
+ curthread.raise(TimeoutError.new("timeout"))
21
+ curthread.pass
22
+ end
23
+ }
24
+
25
+ count = opts[:retry]
26
+ begin
27
+ begin
28
+ break if blk.call
29
+ end while !timedout && ((count -= 1) >= 0)
30
+ rescue TimeoutError => e
31
+ raise e
32
+ rescue RuntimeError => e
33
+ if respond_to?(:logger)
34
+ logger.debug("Caught Error. To be retrying....: #{e}")
35
+ end
36
+ retry if (count -= 1) >= 0
37
+ ensure
38
+ curthread = nil
39
+ EventMachine.cancel_timer(timersig) rescue nil
40
+ end
41
+ end
42
+
43
+ class CommandError < StandardError
44
+ attr_reader :stderr, :stdout
45
+ def initialize(msg, stdout, stderr)
46
+ super(msg)
47
+ @stdout = stdout
48
+ @stderr = stderr
49
+ end
50
+ end
51
+
52
+ def sh(cmd, args=[], opts={})
53
+ opts = opts.merge({:expect_exitcode=>0})
54
+ cmd = sprintf(cmd, *args.map {|a| Shellwords.shellescape(a.to_s) })
55
+
56
+ outbuf = errbuf = ''
57
+ blk = proc {|pid, stdin, stdout, stderr|
58
+ stdin.close
59
+ outbuf = stdout.read
60
+ errbuf = stderr.read
61
+ }
62
+ stat = Open4::popen4(cmd, &blk)
63
+ if self.respond_to?(:logger)
64
+ logger.debug("Exec command (pid=#{stat.pid}): #{cmd}")
65
+ msg = "Command output:"
66
+ msg << "\nSTDOUT:\n#{outbuf.strip}" if outbuf && outbuf.strip.size > 0
67
+ msg << "\nSTDERR:\n#{errbuf.strip}" if errbuf && errbuf.strip.size > 0
68
+ logger.debug(msg)
69
+ end
70
+ if stat.exitstatus != opts[:expect_exitcode]
71
+ raise CommandError.new("Unexpected exit code=#{stat.exitstatus} (expected=#{opts[:expect_exitcode]})", \
72
+ outbuf, errbuf)
73
+ end
74
+ true
75
+ end
76
+ end
77
+
78
+ end
79
+ end
@@ -3,10 +3,6 @@
3
3
  module Dcmgr::Models
4
4
  class Account < BaseNew
5
5
  taggable 'a'
6
- with_timestamps
7
- plugin :single_table_inheritance, :uuid, :model_map=>{}
8
- plugin :subclasses
9
-
10
6
  # pk has to be overwritten by the STI subclasses.
11
7
  unrestrict_primary_key
12
8
 
@@ -17,8 +13,14 @@ module Dcmgr::Models
17
13
  String :description, :size=>100
18
14
  Fixnum :enabled, :default=>ENABLED, :null=>false
19
15
  end
16
+ with_timestamps
20
17
 
21
- one_to_many :tags
18
+ one_to_many :tags, :dataset=>lambda { Tag.filter(:account_id=>self.canonical_uuid); }
19
+
20
+ # sti plugin has to be loaded at lower position.
21
+ plugin :subclasses
22
+ plugin :single_table_inheritance, :uuid, :model_map=>{}
23
+
22
24
 
23
25
  def disable?
24
26
  self.enabled == DISABLED
@@ -28,13 +30,6 @@ module Dcmgr::Models
28
30
  self.enabled == ENABLED
29
31
  end
30
32
 
31
- def to_hash_document
32
- h = self.values.dup
33
- h[:id] = h[:uuid] = self.canonical_uuid
34
- h
35
- end
36
-
37
-
38
33
  # STI class variable setter, getter methods.
39
34
  class << self
40
35
  def default_values
@@ -98,6 +93,18 @@ module Dcmgr::Models
98
93
  self.enabled = Account::ENABLED
99
94
  end
100
95
  end
96
+
97
+ SystemAccount.define_account(:SharedPoolAccount) do
98
+ pk 101
99
+ uuid 'shpoolxx'
100
+ description 'system account for shared resources'
101
+
102
+ # SahredPoolAccount is always enabled.
103
+ def before_save
104
+ super
105
+ self.enabled = Account::ENABLED
106
+ end
107
+ end
101
108
 
102
109
  end
103
110
  end
@@ -50,6 +50,7 @@ module Dcmgr::Models
50
50
  column(:uuid, String, :size=>8, :null=>false, :fixed=>true, :unique=>true)
51
51
  end
52
52
  }
53
+ model.many_to_many :tags, :dataset=>lambda { Tag.join(TagMapping.table_name, :tag_id=>:id, :uuid=>self.canonical_uuid); }
53
54
  end
54
55
 
55
56
  module InstanceMethods
@@ -65,6 +66,12 @@ module Dcmgr::Models
65
66
  self[:uuid] ||= Array.new(8) do UUID_TABLE[rand(UUID_TABLE.size)]; end.join
66
67
  end
67
68
 
69
+ # model hook
70
+ def after_destroy
71
+ super
72
+ TagMapping.filter(:uuid=>self.canonical_uuid).delete
73
+ end
74
+
68
75
  # Returns canonicalized uuid which has the form of
69
76
  # "{uuid_prefix}-{uuid}".
70
77
  def canonical_uuid
@@ -74,36 +81,56 @@ module Dcmgr::Models
74
81
 
75
82
  # Put the tag on the object.
76
83
  #
77
- # This method just delegates the method call of Tag#label().
78
- # @params [Models::Tag,String] tag_or_tag_uuid 'tag-xxxx' is expected when the type is string
79
- def label_tag(tag_or_tag_uuid)
80
- tag = case tag_or_tag_uuid
84
+ # @params [Models::Tag,String,Symbol] arg1
85
+ # @params [String,NilClass] arg2
86
+ # @params [String,NilClass] arg3
87
+ #
88
+ # @example
89
+ # lable_tag('tag-xxxxx')
90
+ # t = Tag['tag-xxxx']
91
+ # label_tag(t)
92
+ # label_tag(:NetworkPool, 'newname1', 'account_id')
93
+ def label_tag(arg1, arg2=nil, arg3=nil)
94
+ tag = case arg1
81
95
  when String
82
- Tag[tag_or_tag_uuid]
96
+ Tag[arg1]
97
+ when Symbol
98
+ acctid = arg3 || self.respond_to?(:account_id) ? self.account_id : raise("Unknown Account ID")
99
+ Dcmgr::Tags.const_get(arg1).find_or_create(:account_id=>acctid, :name=>arg2)
83
100
  when Tag
84
- tag_or_tag_uuid
101
+ arg1
85
102
  else
86
- raise ArgumentError, "Invalid type: #{tag_or_tag_uuid.class}"
103
+ raise ArgumentError, "Invalid type: #{arg1.class}"
87
104
  end
88
-
89
- tag.label(self.uuid)
105
+ raise "Root Tag class can not be used" unless tag.class < Tag
106
+ tag.label(self.canonical_uuid)
90
107
  end
91
108
 
92
109
  # Remove the labeled tag from the object
93
110
  #
94
- # This method just delegates the method call of Tag#unlabel().
95
- # @params [Models::Tag,String] tag_or_tag_uuid 'tag-xxxx' is expected when the type is string
96
- def unlabel_tag(tag_or_tag_uuid)
97
- tag = case tag_or_tag_uuid
111
+ # @params [Models::Tag,String,Symbol] arg1
112
+ # @params [String,NilClass] arg2
113
+ # @params [String,NilClass] arg3
114
+ #
115
+ # @example
116
+ # unlable_tag('tag-xxxxx')
117
+ # t = Tag['tag-xxxx']
118
+ # unlabel_tag(t)
119
+ # unlabel_tag(:NetworkPool, 'newname1', 'account_id')
120
+ def unlabel_tag(arg1, arg2=nil, arg3=nil)
121
+ tag = case arg1
98
122
  when String
99
- Tag[tag_or_tag_uuid]
123
+ Tag[arg1]
124
+ when Symbol
125
+ acctid = arg3 || self.respond_to?(:account_id) ? self.account_id : raise("Unknown Account ID")
126
+ Dcmgr::Tags.const_get(arg1).find(:account_id=>acctid, :name=>arg2)
100
127
  when Tag
101
- tag_or_tag_uuid
128
+ arg1
102
129
  else
103
- raise ArgumentError, "Invalid type: #{tag_or_tag_uuid.class}"
130
+ raise ArgumentError, "Invalid type: #{arg1.class}"
104
131
  end
105
132
 
106
- tag.unlabel(self.uuid)
133
+ tag.unlabel(self.canonical_uuid)
107
134
  end
108
135
 
109
136
  def to_hash()
@@ -256,7 +283,116 @@ module Dcmgr::Models
256
283
  end
257
284
 
258
285
  end
259
-
286
+
287
+ # This plugin is to archive the changes on each column of the model
288
+ # to a history table.
289
+ #
290
+ # plugin ArchiveChangedColumn, :your_history_table
291
+ # or
292
+ # plugin ArchiveChangedColumn
293
+ # history_dataset = DB[:history_table]
294
+ #
295
+ # The history table should have the schema below:
296
+ # schema do
297
+ # Fixnum :id, :null=>false, :primary_key=>true
298
+ # String :uuid, :size=>50, :null=>false
299
+ # String :attr, :null=>false
300
+ # String :vchar_value, :null=>true
301
+ # String :blob_value, :null=>true, :text=>true
302
+ # Time :created_at, :null=>false
303
+ # index [:uuid, :created_at]
304
+ # index [:uuid, :attr]
305
+ # end
306
+ module ArchiveChangedColumn
307
+ def self.configure(model, history_table=nil)
308
+ model.history_dataset = case history_table
309
+ when NilClass
310
+ nil
311
+ when String,Symbol
312
+ model.db.from(history_table)
313
+ when Class
314
+ raise "Unknown type" unless history_table < Sequel::Model
315
+ history_table.dataset
316
+ when Sequel::Dataset
317
+ history_table
318
+ else
319
+ raise "Unknown type"
320
+ end
321
+ end
322
+
323
+ module ClassMethods
324
+ def history_dataset=(ds)
325
+ @history_ds = ds
326
+ end
327
+
328
+ def history_dataset
329
+ @history_ds
330
+ end
331
+ end
332
+
333
+ module InstanceMethods
334
+ def history_snapshot(at)
335
+ raise TypeError unless at.is_a?(Time)
336
+
337
+ if self.created_at > at || (!self.terminated_at.nil? && self.terminated_at < at)
338
+ raise "#{at} is not in the range of the object's life span."
339
+ end
340
+
341
+ ss = self.dup
342
+ # SELECT * FROM (SELECT * FROM `instance_histories` WHERE
343
+ # (`uuid` = 'i-ezsrs132') AND created_at <= '2010-11-30 23:08:05'
344
+ # ORDER BY created_at DESC) AS a GROUP BY a.attr;
345
+ ds = self.class.history_dataset.filter('uuid=? AND created_at <= ?', self.canonical_uuid, at).order(:created_at.desc)
346
+ ds = ds.from_self.group_by(:attr)
347
+ ds.all.each { |h|
348
+ if !h[:blob_value].nil?
349
+ ss.send("#{h[:attr]}=", typecast_value(h[:attr], h[:blob_value]))
350
+ else
351
+ ss.send("#{h[:attr]}=", typecast_value(h[:attr], h[:vchar_value]))
352
+ end
353
+ }
354
+ # take care for serialized columns by serialization plugin.
355
+ ss.deserialized_values.clear if ss.respond_to?(:deserialized_values)
356
+
357
+ ss
358
+ end
359
+
360
+ def before_create
361
+ return false if super == false
362
+ store_changes(self.columns)
363
+ true
364
+ end
365
+
366
+ def before_update
367
+ return false if super == false
368
+ store_changes(self.changed_columns)
369
+ true
370
+ end
371
+
372
+ private
373
+ def store_changes(cols_stored)
374
+ return if cols_stored.nil? || cols_stored.empty?
375
+ common_rec = {
376
+ :uuid=>self.canonical_uuid,
377
+ :created_at => Time.now,
378
+ }
379
+
380
+ cols_stored.each { |c|
381
+ hist_rec = common_rec.dup
382
+ hist_rec[:attr] = c.to_s
383
+
384
+ coldef = self.class.db_schema[c]
385
+ case coldef[:type]
386
+ when :text,:blob
387
+ hist_rec[:blob_value]= (new? ? (self[c] || coldef[:default]) : self[c])
388
+ else
389
+ hist_rec[:vchar_value]=(new? ? (self[c] || coldef[:default]) : self[c])
390
+ end
391
+ self.class.history_dataset.insert(hist_rec)
392
+ }
393
+ end
394
+ end
395
+ end
260
396
 
261
397
  class BaseNew < Sequel::Model
262
398
 
@@ -0,0 +1,21 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Dcmgr::Models
4
+ # History record table for ArchiveChangedColumn plugin
5
+ class History < BaseNew
6
+ set_dataset(:histories)
7
+
8
+ inheritable_schema do
9
+ String :uuid, :size=>50, :null=>false
10
+ String :attr, :null=>false
11
+ String :vchar_value, :null=>true
12
+ String :blob_value, :null=>true, :text=>true
13
+ Time :created_at, :null=>false
14
+ index [:uuid, :created_at]
15
+ index [:uuid, :attr]
16
+ end
17
+
18
+ plugin :timestamps
19
+
20
+ end
21
+ end
@@ -19,16 +19,15 @@ module Dcmgr::Models
19
19
 
20
20
  String :arch, :size=>10, :null=>false # :x86, :x86_64
21
21
  String :hypervisor, :size=>30, :null=>false
22
- Fixnum :network_id, :null=>false
23
22
 
24
23
  Fixnum :offering_cpu_cores, :null=>false, :unsigned=>true
25
24
  Fixnum :offering_memory_size, :null=>false, :unsigned=>true
26
- Fixnum :allow_memory_overcommit, :null=>false, :default=>1
25
+
26
+ index :node_id
27
27
  end
28
28
 
29
29
  one_to_many :instances
30
30
  many_to_one :node, :class=>Isono::Models::NodeState, :key=>:node_id, :primary_key=>:node_id
31
- many_to_one :network
32
31
 
33
32
  def after_initialize
34
33
  super
@@ -66,10 +65,12 @@ module Dcmgr::Models
66
65
  # @param [Models::Account] account
67
66
  # @param [Models::Image] image
68
67
  # @param [Models::InstanceSpec] spec
68
+ # @param [Models::Network] network
69
69
  # @return [Models::Instance] created new Instance object.
70
- def create_instance(account, image, spec, &blk)
70
+ def create_instance(account, image, spec, network, &blk)
71
71
  raise ArgumentError unless image.is_a?(Image)
72
72
  raise ArgumentError unless spec.is_a?(InstanceSpec)
73
+ raise ArgumentError unless network.is_a?(Network)
73
74
  i = Instance.new &blk
74
75
  i.account_id = account.canonical_uuid
75
76
  i.image = image
@@ -77,9 +78,8 @@ module Dcmgr::Models
77
78
  i.host_pool = self
78
79
  i.save
79
80
 
80
- # TODO: set vnic spec from InstanceSpec
81
- vnic = i.add_nic
82
- IpLease.lease(vnic)
81
+ vnic = i.add_nic(network)
82
+ IpLease.lease(vnic, network)
83
83
  i
84
84
  end
85
85
 
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Dcmgr::Models
4
+ # hostname table for each instance to ensure uniqueness.
5
+ class HostnameLease < BaseNew
6
+
7
+ inheritable_schema do
8
+ String :account_id, :null=>false, :size=>50
9
+ String :hostname, :null=>false, :size=>32
10
+
11
+ index [:account_id, :hostname], {:unique=>true}
12
+ end
13
+ with_timestamps
14
+ end
15
+ end
@@ -16,17 +16,16 @@ module Dcmgr::Models
16
16
  Fixnum :instance_spec_id, :null=>false
17
17
  String :state, :size=>20, :null=>false, :default=>:init.to_s
18
18
  String :status, :size=>20, :null=>false, :default=>:init.to_s
19
- String :hostname, :null=>false
19
+ String :hostname, :null=>false, :size=>32
20
20
  String :ssh_key_pair_id
21
+ Fixnum :ha_enabled, :null=>false, :default=>0
21
22
 
22
23
  Text :user_data, :null=>false, :default=>''
23
24
  Text :runtime_config, :null=>false, :default=>''
24
25
 
25
- Time :terminated_at
26
+ Time :terminated_at
26
27
  index :state
27
28
  index :terminated_at
28
- # can not use same hostname within an account.
29
- index [:account_id, :hostname], {:unique=>true}
30
29
  end
31
30
  with_timestamps
32
31
 
@@ -41,29 +40,116 @@ module Dcmgr::Models
41
40
  many_to_many :netfilter_groups, :join_table=>:instance_netfilter_groups
42
41
  many_to_one :ssh_key_pair
43
42
 
43
+ plugin ArchiveChangedColumn, :histories
44
+
44
45
  subset(:lives, {:terminated_at => nil})
45
46
 
46
47
  # serialization plugin must be defined at the bottom of all class
47
48
  # method calls.
48
49
  # Possible column data:
49
50
  # kvm:
50
- # {:vnc_port=>11}
51
+ # {:vnc_port=>11, :telnet_port=>1111}
51
52
  plugin :serialization
52
53
  serialize_attributes :yaml, :runtime_config
53
54
 
55
+ module ValidationMethods
56
+ def self.hostname_uniqueness(account_id, hostname)
57
+ HostnameLease.filter(:account_id=>account_id, :hostname=>hostname).empty?
58
+ end
59
+ end
60
+
54
61
  def validate
55
62
  super
56
63
 
57
- # TODO: hostname column validation
64
+ unless self.hostname =~ /\A[0-9a-z][0-9a-z\-]{0,31}\Z/
65
+ errors.add(:hostname, "Invalid hostname syntax")
66
+ end
67
+
68
+ # uniqueness check for hostname
69
+ if changed_columns.include?(:hostname)
70
+ proc_test = lambda {
71
+ unless ValidationMethods.hostname_uniqueness(self.account_id, self.hostname)
72
+ errors.add(:hostname, "Duplicated hostname: #{self.hostname}")
73
+ end
74
+ }
75
+
76
+ if new?
77
+ proc_test.call
78
+ else
79
+ orig = self.dup.refresh
80
+ # do nothing if orig.hostname == self.hostname
81
+ if orig.hostname != self.hostname
82
+ proc_test.call
83
+ end
84
+ end
85
+ @update_hostname = true
86
+ end
87
+
88
+ # check runtime_config column
89
+ case self.hypervisor
90
+ when HostPool::HYPERVISOR_KVM
91
+ r1 = self.runtime_config
92
+ self.host_pool.instances.each { |i|
93
+ next true if i.id == self.id
94
+ r2 = i.runtime_config
95
+ unless r1[:vnc_port] != r2[:vnc_port] && r1[:telnet_port] != r2[:telnet_port]
96
+ errors.add(:runtime_config, "#{self.canonical_uuid}.runtime_config conflicted with #{i.canonical_uuid}")
97
+ break
98
+ end
99
+ }
100
+ end
58
101
  end
59
102
 
60
103
  def before_validation
104
+ self[:user_data] ||= ''
105
+ self[:hostname] ||= self.uuid
106
+ self[:hostname] = self[:hostname].downcase
61
107
  super
108
+ end
62
109
 
63
- self[:user_data] = '' if self.user_data.nil?
64
- self[:hostname] = self.uuid if self.hostname.nil?
110
+ def before_save
111
+ if @update_hostname
112
+ if new?
113
+ HostnameLease.create(:account_id=>self.account_id,
114
+ :hostname=>self.hostname)
115
+ else
116
+ orig = self.dup.refresh
117
+ # do nothing if orig.hostname == self.hostname
118
+ if orig.hostname != self.hostname
119
+
120
+ orig_name = HostnameLease.filter(:account_id=>self.account_id,
121
+ :hostname=>orig.hostname).first
122
+ orig_name.hostname = self.hostname
123
+ orig_name.save
124
+ end
125
+ end
126
+ @update_hostname = false
127
+ end
128
+
129
+ super
65
130
  end
66
131
 
132
+ def before_destroy
133
+ HostnameLease.filter(:account_id=>self.account_id, :hostname=>self.hostname).destroy
134
+ self.instance_nic.each { |o| o.destroy }
135
+ self.instance_netfilter_groups.each{|o| o.destroy }
136
+ self.volume.each { |v|
137
+ v.instance_id = nil
138
+ v.state = :available
139
+ v.save
140
+ }
141
+ super
142
+ end
143
+
144
+ # override Sequel::Model#_delete not to delete rows but to set
145
+ # delete flags.
146
+ def _delete
147
+ self.terminated_at ||= Time.now
148
+ self.state = :terminated if self.state != :terminated
149
+ self.status = :offline if self.status != :offline
150
+ self.save
151
+ end
152
+
67
153
  # dump column data as hash with details of associated models.
68
154
  # this is for internal use.
69
155
  def to_hash
@@ -74,11 +160,12 @@ module Dcmgr::Models
74
160
  :host_pool=>host_pool.to_hash,
75
161
  :instance_nics=>instance_nic.map {|n| n.to_hash },
76
162
  :instance_spec=>instance_spec.to_hash,
163
+ :ips => instance_nic.map { |n| n.ip.ipv4 if n.ip },
77
164
  })
78
165
  h[:volume]={}
79
166
  if self.volume
80
167
  self.volume.each { |v|
81
- h[:volume][v.canonical_uuid] = v.to_hash_document
168
+ h[:volume][v.canonical_uuid] = v.to_hash
82
169
  }
83
170
  end
84
171
  h
@@ -92,8 +179,8 @@ module Dcmgr::Models
92
179
  # :cpu_cores
93
180
  # :memory_size
94
181
  # :image_id
95
- # :network => {'global1'=>{:ipaddr=>'111.111.111.111'}}
96
- # :volume => {'uuid'=>{:guest_device_name=>,}}
182
+ # :network => [{:network_name=>'nw-xxxxxxx', :ipaddr=>'111.111.111.111'}]
183
+ # :volume => [{'uuid'=>{:guest_device_name=>,}]
97
184
  # :ssh_key_pair => 'xxxxx',
98
185
  # :netfilter_group => ['rule1', 'rule2']
99
186
  # :created_at
@@ -122,7 +209,7 @@ module Dcmgr::Models
122
209
  instance_nic.each { |n|
123
210
  if n.ip
124
211
  h[:network] << {
125
- :network_name => n.ip.network.name,
212
+ :network_name => n.network.canonical_uuid,
126
213
  :ipaddr => n.ip.ipv4
127
214
  }
128
215
  end
@@ -169,13 +256,11 @@ module Dcmgr::Models
169
256
  self.instance_spec.config
170
257
  end
171
258
 
172
- def add_nic(vifname=nil, vendor_id=nil)
173
- vifname ||= "vif-#{self[:uuid]}"
259
+ def add_nic(network, vendor_id=nil)
174
260
  # TODO: get default vendor ID based on the hypervisor.
175
261
  vendor_id ||= '00:ff:f1'
176
- nic = InstanceNic.new({:vif=>vifname,
177
- :mac_addr=>vendor_id
178
- })
262
+ nic = InstanceNic.new(:mac_addr=>vendor_id)
263
+ nic.network = network
179
264
  nic.instance = self
180
265
  nic.save
181
266
  end
@@ -202,15 +287,15 @@ module Dcmgr::Models
202
287
  self.instance_nic.map { |nic| nic.ip }
203
288
  end
204
289
 
205
- def netfilter_group_instances
206
- instances = self.netfilter_groups.map { |g| g.instances }
207
-
208
- instances.flatten!.uniq! if instances.size > 0
209
- instances
210
- end
290
+ # def netfilter_group_instances
291
+ # instances = self.netfilter_groups.map { |g| g.instances }
292
+ #
293
+ # instances.flatten!.uniq! if instances.size > 0
294
+ # instances
295
+ # end
211
296
 
212
297
  def fqdn_hostname
213
- sprintf("%s.%s.%s", self.hostname, self.account.uuid, self.host_pool.network.domain_name)
298
+ sprintf("%s.%s.%s", self.hostname, self.account.uuid, self.nic.first.network.domain_name)
214
299
  end
215
300
 
216
301
  # Retrieve all networks belong to this instance
@@ -221,7 +306,7 @@ module Dcmgr::Models
221
306
  }.map { |nic|
222
307
  nic.ip.network
223
308
  }.group_by { |net|
224
- net.name
309
+ net.canonical_uuid
225
310
  }.values.map { |i|
226
311
  i.first
227
312
  }
@@ -251,5 +336,9 @@ module Dcmgr::Models
251
336
  VolumeSnapshot.lock!
252
337
  IpLease.lock!
253
338
  end
339
+
340
+ def live?
341
+ self.terminated_at.nil?
342
+ end
254
343
  end
255
344
  end