wakame-vdc-dcmgr 10.12.0 → 11.06.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +164 -201
- data/Rakefile +6 -11
- data/bin/collector +10 -24
- data/config/dcmgr.conf.example +18 -6
- data/config/initializers/isono.rb +7 -23
- data/config/initializers/sequel.rb +11 -2
- data/lib/dcmgr.rb +70 -11
- data/lib/dcmgr/cli/base.rb +74 -0
- data/lib/dcmgr/cli/errors.rb +59 -0
- data/lib/dcmgr/cli/group.rb +101 -0
- data/lib/dcmgr/cli/host.rb +101 -0
- data/lib/dcmgr/cli/image.rb +108 -0
- data/lib/dcmgr/cli/keypair.rb +72 -0
- data/lib/dcmgr/cli/network.rb +198 -0
- data/lib/dcmgr/cli/quota.rb +28 -0
- data/lib/dcmgr/cli/spec.rb +82 -0
- data/lib/dcmgr/cli/storage.rb +88 -0
- data/lib/dcmgr/cli/tag.rb +81 -0
- data/lib/dcmgr/cli/vlan.rb +53 -0
- data/lib/dcmgr/drivers/hypervisor.rb +33 -0
- data/lib/dcmgr/drivers/iijgio_storage.rb +37 -0
- data/lib/dcmgr/drivers/kvm.rb +118 -0
- data/lib/dcmgr/drivers/lxc.rb +167 -0
- data/lib/dcmgr/drivers/s3_storage.rb +39 -0
- data/lib/dcmgr/drivers/snapshot_storage.rb +51 -0
- data/lib/dcmgr/endpoints/core_api.rb +188 -324
- data/lib/dcmgr/endpoints/core_api_mock.rb +52 -3
- data/lib/dcmgr/endpoints/errors.rb +73 -32
- data/lib/dcmgr/endpoints/metadata.rb +163 -16
- data/lib/dcmgr/helpers/cli_helper.rb +1 -1
- data/lib/dcmgr/helpers/nic_helper.rb +35 -0
- data/lib/dcmgr/logger.rb +5 -1
- data/lib/dcmgr/messaging_client.rb +117 -0
- data/lib/dcmgr/models/account.rb +27 -3
- data/lib/dcmgr/models/base_new.rb +21 -7
- data/lib/dcmgr/models/host_pool.rb +27 -7
- data/lib/dcmgr/models/image.rb +31 -3
- data/lib/dcmgr/models/instance.rb +72 -23
- data/lib/dcmgr/models/instance_nic.rb +12 -2
- data/lib/dcmgr/models/instance_spec.rb +16 -0
- data/lib/dcmgr/models/ip_lease.rb +37 -1
- data/lib/dcmgr/models/netfilter_group.rb +7 -7
- data/lib/dcmgr/models/network.rb +42 -3
- data/lib/dcmgr/models/quota.rb +25 -0
- data/lib/dcmgr/models/request_log.rb +26 -11
- data/lib/dcmgr/models/ssh_key_pair.rb +14 -1
- data/lib/dcmgr/models/storage_pool.rb +19 -72
- data/lib/dcmgr/models/tag.rb +5 -0
- data/lib/dcmgr/models/vlan_lease.rb +8 -0
- data/lib/dcmgr/models/volume.rb +26 -8
- data/lib/dcmgr/models/volume_snapshot.rb +37 -0
- data/lib/dcmgr/node_modules/hva_collector.rb +56 -36
- data/lib/dcmgr/node_modules/instance_ha.rb +1 -1
- data/lib/dcmgr/node_modules/instance_monitor.rb +70 -0
- data/lib/dcmgr/node_modules/service_netfilter.rb +914 -0
- data/lib/dcmgr/node_modules/sta_collector.rb +7 -30
- data/lib/dcmgr/rack/request_logger.rb +60 -0
- data/lib/dcmgr/rack/run_initializer.rb +42 -0
- data/lib/dcmgr/rpc/hva_handler.rb +388 -0
- data/lib/dcmgr/rubygems.rb +7 -0
- data/lib/dcmgr/storage_service.rb +98 -0
- data/lib/dcmgr/tags.rb +2 -2
- data/lib/dcmgr/version.rb +8 -0
- data/lib/ext/time.rb +8 -0
- data/lib/sinatra/respond_to.rb +3 -0
- data/lib/sinatra/sequel_transaction.rb +20 -5
- data/web/api/config.ru +9 -13
- data/web/metadata/config.ru +10 -13
- metadata +162 -120
- data/lib/dcmgr/models/physical_host.rb +0 -67
- data/lib/dcmgr/web/base.rb +0 -21
data/lib/dcmgr/logger.rb
CHANGED
@@ -4,7 +4,11 @@ require 'logger'
|
|
4
4
|
module Dcmgr
|
5
5
|
module Logger
|
6
6
|
|
7
|
-
|
7
|
+
# for passenger, messages in STDOUT are not appeared in
|
8
|
+
# error.log. $> is changed in initializers/logger.rb as per the
|
9
|
+
# server environment. so that here also refers $> instead of STDOUT or
|
10
|
+
# STDERR constant.
|
11
|
+
@logdev = ::Logger::LogDevice.new($>)
|
8
12
|
|
9
13
|
def self.default_logdev
|
10
14
|
@logdev
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'isono'
|
4
|
+
require 'eventmachine'
|
5
|
+
|
6
|
+
module Dcmgr
|
7
|
+
# @example Sync RPC call with object method.
|
8
|
+
# mc = MessagingClient.start
|
9
|
+
# puts mc.request('endpoint', 'func1', xxxx, xxxx)
|
10
|
+
# puts mc.request('endpoint', 'func2', xxx, xxx)
|
11
|
+
#
|
12
|
+
# @example Sync RPC call using delegated object
|
13
|
+
# mc = MessagingClient.start
|
14
|
+
# endpoint = mc.sync_rpc('endpoint')
|
15
|
+
# endpoint.func1(xxxx, xxxx)
|
16
|
+
# endpoint.func2(xxx, xxx)
|
17
|
+
#
|
18
|
+
class MessagingClient < Isono::Node
|
19
|
+
include Logger
|
20
|
+
include Isono
|
21
|
+
|
22
|
+
def self.start(amqp_uri, manifest=nil, &blk)
|
23
|
+
node = self.new(manifest, &blk)
|
24
|
+
|
25
|
+
if EventMachine.reactor_thread?
|
26
|
+
EventMachine.schedule {
|
27
|
+
node.connect(amqp_uri)
|
28
|
+
}
|
29
|
+
else
|
30
|
+
q = ::Queue.new
|
31
|
+
EventMachine.schedule {
|
32
|
+
node.connect(amqp_uri) { |type|
|
33
|
+
q << type
|
34
|
+
}
|
35
|
+
}
|
36
|
+
case q.deq
|
37
|
+
when :success
|
38
|
+
when :error
|
39
|
+
raise "Connection failed: #{amqp_uri}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
node
|
44
|
+
end
|
45
|
+
|
46
|
+
def stop
|
47
|
+
if connected?
|
48
|
+
close {
|
49
|
+
EventMachine.schedule {
|
50
|
+
EventMachine.stop
|
51
|
+
}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def initialize(m=nil, &blk)
|
57
|
+
m ||= Manifest.new(Dir.pwd) {
|
58
|
+
node_name 'dcmgr'
|
59
|
+
node_instance_id Util.gen_id
|
60
|
+
|
61
|
+
load_module NodeModules::EventChannel
|
62
|
+
load_module NodeModules::RpcChannel
|
63
|
+
load_module NodeModules::JobChannel
|
64
|
+
}
|
65
|
+
m.instance_eval(&blk) if blk
|
66
|
+
super(m)
|
67
|
+
end
|
68
|
+
|
69
|
+
class RpcSyncDelegator
|
70
|
+
attr_reader :endpoint
|
71
|
+
|
72
|
+
def initialize(rpc, endpoint, opts={})
|
73
|
+
@rpc = rpc
|
74
|
+
@endpoint = endpoint
|
75
|
+
@opts = {:timeout=>0.0, :oneshot=>false}.merge(opts)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
def method_missing(m, *args)
|
80
|
+
if @opts[:oneshot]
|
81
|
+
oneshot_request(m, *args)
|
82
|
+
else
|
83
|
+
normal_request(m, *args)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def oneshot_request(m, *args)
|
88
|
+
@rpc.request(@endpoint, m, *args) { |req|
|
89
|
+
req.oneshot = true
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def normal_request(m, *args)
|
94
|
+
@rpc.request(@endpoint, m, *args)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def sync_rpc(endpoint, opts={})
|
99
|
+
rpc = NodeModules::RpcChannel.new(self)
|
100
|
+
RpcSyncDelegator.new(rpc, endpoint, opts)
|
101
|
+
end
|
102
|
+
|
103
|
+
def request(endpoint, key, *args, &blk)
|
104
|
+
rpc = NodeModules::RpcChannel.new(self)
|
105
|
+
rpc.request(endpoint, key, *args, &blk)
|
106
|
+
end
|
107
|
+
|
108
|
+
def submit(job_endpoint, key, *args)
|
109
|
+
NodeModules::JobChannel.new(self).submit(job_endpoint, key, *args)
|
110
|
+
end
|
111
|
+
|
112
|
+
def event_publish(evname, opts={})
|
113
|
+
NodeModules::EventChannel.new(self).publish(evname, opts)
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
data/lib/dcmgr/models/account.rb
CHANGED
@@ -16,6 +16,7 @@ module Dcmgr::Models
|
|
16
16
|
with_timestamps
|
17
17
|
|
18
18
|
one_to_many :tags, :dataset=>lambda { Tag.filter(:account_id=>self.canonical_uuid); }
|
19
|
+
one_to_one :quota, :class=>Quota, :key=>:account_id
|
19
20
|
|
20
21
|
# sti plugin has to be loaded at lower position.
|
21
22
|
plugin :subclasses
|
@@ -30,6 +31,17 @@ module Dcmgr::Models
|
|
30
31
|
self.enabled == ENABLED
|
31
32
|
end
|
32
33
|
|
34
|
+
def after_create
|
35
|
+
self.quota = Quota.create
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
39
|
+
def before_destroy
|
40
|
+
self.quota.destroy unless self.quota.nil?
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
|
33
45
|
# STI class variable setter, getter methods.
|
34
46
|
class << self
|
35
47
|
def default_values
|
@@ -46,12 +58,13 @@ module Dcmgr::Models
|
|
46
58
|
def uuid(uuid=nil)
|
47
59
|
if uuid.is_a?(String)
|
48
60
|
uuid = uuid.downcase
|
49
|
-
|
61
|
+
unless self.check_trimmed_uuid_format(uuid)
|
50
62
|
raise "Invalid syntax of uuid: #{uuid}"
|
51
63
|
end
|
52
64
|
default_values[:uuid] = uuid
|
53
65
|
end
|
54
|
-
|
66
|
+
raise("#{self}.uuid is unset. Set the unique number") unless default_values[:uuid]
|
67
|
+
"#{uuid_prefix}-#{default_values[:uuid]}"
|
55
68
|
end
|
56
69
|
|
57
70
|
def description(description=nil)
|
@@ -80,8 +93,19 @@ module Dcmgr::Models
|
|
80
93
|
Account.subclasses.each { |m|
|
81
94
|
Account.create(m.default_values.dup)
|
82
95
|
}
|
83
|
-
end
|
84
96
|
|
97
|
+
# create shared resource pool tags
|
98
|
+
Dcmgr::Tags::HostPool.create(:account_id=>SystemAccount::SharedPoolAccount.uuid,
|
99
|
+
:uuid=>'shhost',
|
100
|
+
:name=>"default_shared_hosts")
|
101
|
+
Dcmgr::Tags::NetworkPool.create(:account_id=>SystemAccount::SharedPoolAccount.uuid,
|
102
|
+
:uuid=>'shnet',
|
103
|
+
:name=>"default_shared_networks")
|
104
|
+
Dcmgr::Tags::StoragePool.create(:account_id=>SystemAccount::SharedPoolAccount.uuid,
|
105
|
+
:uuid=>'shstor',
|
106
|
+
:name=>"default_shared_storages")
|
107
|
+
end
|
108
|
+
|
85
109
|
SystemAccount.define_account(:DatacenterAccount) do
|
86
110
|
pk 100
|
87
111
|
uuid '00000000'
|
@@ -4,9 +4,6 @@ require 'sequel/model'
|
|
4
4
|
|
5
5
|
|
6
6
|
module Dcmgr::Models
|
7
|
-
class InvalidUUIDError < StandardError; end
|
8
|
-
class UUIDPrefixDuplication < StandardError; end
|
9
|
-
|
10
7
|
# Sequal::Model plugin to inject the Taggable feature to the model
|
11
8
|
# class.
|
12
9
|
#
|
@@ -187,6 +184,11 @@ module Dcmgr::Models
|
|
187
184
|
raise InvalidUUIDError, "Invalid uuid or unsupported uuid: #{p_uuid} in #{self}"
|
188
185
|
end
|
189
186
|
|
187
|
+
# Checks the general uuid syntax
|
188
|
+
def check_trimmed_uuid_format(uuid)
|
189
|
+
uuid.match(/^[a-z0-9 ]*$/) && uuid.length <= 8
|
190
|
+
end
|
191
|
+
|
190
192
|
# Checks the uuid syntax if it is for the Taggable class.
|
191
193
|
def check_uuid_format(uuid)
|
192
194
|
uuid =~ /^#{self.uuid_prefix}-/
|
@@ -397,11 +399,18 @@ module Dcmgr::Models
|
|
397
399
|
class BaseNew < Sequel::Model
|
398
400
|
|
399
401
|
LOCK_TABLES_KEY='__locked_tables'
|
402
|
+
|
403
|
+
def self.default_row_lock_mode=(mode)
|
404
|
+
raise ArgumentError unless [nil, :share, :update].member?(mode)
|
405
|
+
@default_row_lock_mode = mode
|
406
|
+
end
|
400
407
|
|
401
|
-
def self.lock!
|
408
|
+
def self.lock!(mode=nil)
|
409
|
+
raise ArgumentError unless [nil, :share, :update].member?(mode)
|
410
|
+
mode ||= @default_row_lock_mode
|
402
411
|
locktbls = Thread.current[LOCK_TABLES_KEY]
|
403
412
|
if locktbls
|
404
|
-
locktbls[self.db.uri.to_s + @dataset.first_source_alias.to_s]=
|
413
|
+
locktbls[self.db.uri.to_s + @dataset.first_source_alias.to_s]=mode
|
405
414
|
end
|
406
415
|
end
|
407
416
|
|
@@ -414,8 +423,9 @@ module Dcmgr::Models
|
|
414
423
|
|
415
424
|
def self.dataset
|
416
425
|
locktbls = Thread.current[LOCK_TABLES_KEY]
|
417
|
-
if locktbls && locktbls[self.db.uri.to_s + @dataset.first_source_alias.to_s]
|
418
|
-
|
426
|
+
if locktbls && (mode = locktbls[self.db.uri.to_s + @dataset.first_source_alias.to_s])
|
427
|
+
# lock mode: :share or :update
|
428
|
+
@dataset.opts = @dataset.opts.merge({:lock=>mode})
|
419
429
|
else
|
420
430
|
@dataset.opts = @dataset.opts.merge({:lock=>nil})
|
421
431
|
end
|
@@ -439,6 +449,10 @@ module Dcmgr::Models
|
|
439
449
|
s
|
440
450
|
end
|
441
451
|
|
452
|
+
# Returns true if this Model has time stamps
|
453
|
+
def with_timestamps?
|
454
|
+
self.columns.include?(:created_at) && self.columns.include?(:updated_at)
|
455
|
+
end
|
442
456
|
|
443
457
|
# Callback when the initial data is setup to the database.
|
444
458
|
def self.install_data
|
@@ -1,18 +1,21 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
+
require 'isono'
|
4
|
+
|
3
5
|
module Dcmgr::Models
|
4
6
|
class HostPool < AccountResource
|
5
7
|
taggable 'hp'
|
6
8
|
with_timestamps
|
7
9
|
|
8
|
-
HYPERVISOR_XEN_34
|
9
|
-
HYPERVISOR_XEN_40
|
10
|
-
HYPERVISOR_KVM
|
10
|
+
HYPERVISOR_XEN_34='xen-3.4'
|
11
|
+
HYPERVISOR_XEN_40='xen-4.0'
|
12
|
+
HYPERVISOR_KVM='kvm'
|
11
13
|
|
12
14
|
ARCH_X86=:x86.to_s
|
13
15
|
ARCH_X86_64=:x86_64.to_s
|
14
16
|
|
15
17
|
SUPPORTED_ARCH=[ARCH_X86, ARCH_X86_64]
|
18
|
+
SUPPORTED_HYPERVISOR=[HYPERVISOR_KVM]
|
16
19
|
|
17
20
|
inheritable_schema do
|
18
21
|
String :node_id, :size=>80, :null=>true
|
@@ -35,8 +38,13 @@ module Dcmgr::Models
|
|
35
38
|
|
36
39
|
def validate
|
37
40
|
super
|
38
|
-
|
39
|
-
|
41
|
+
# for compatibility: hva.xxx or hva-xxxx
|
42
|
+
unless self.node_id =~ /^hva[-.]/
|
43
|
+
errors.add(:node_id, "is invalid ID: #{self.node_id}")
|
44
|
+
end
|
45
|
+
|
46
|
+
if (h = self.class.filter(:node_id=>self.node_id).first) && h.id != self.id
|
47
|
+
errors.add(:node_id, " #{self.node_id} is already been associated to #{h.canonical_uuid} ")
|
40
48
|
end
|
41
49
|
|
42
50
|
unless SUPPORTED_ARCH.member?(self.arch)
|
@@ -75,11 +83,18 @@ module Dcmgr::Models
|
|
75
83
|
i.account_id = account.canonical_uuid
|
76
84
|
i.image = image
|
77
85
|
i.instance_spec = spec
|
86
|
+
i.cpu_cores = spec.cpu_cores
|
87
|
+
i.memory_size = spec.memory_size
|
88
|
+
i.quota_weight = spec.quota_weight
|
78
89
|
i.host_pool = self
|
79
90
|
i.save
|
80
91
|
|
81
92
|
vnic = i.add_nic(network)
|
82
93
|
IpLease.lease(vnic, network)
|
94
|
+
|
95
|
+
#Lease the nat ip in case there is an outside network mapped
|
96
|
+
nat_network = Network.find(:id => vnic[:nat_network_id])
|
97
|
+
IpLease.lease(vnic,nat_network) unless nat_network.nil?
|
83
98
|
i
|
84
99
|
end
|
85
100
|
|
@@ -93,10 +108,15 @@ module Dcmgr::Models
|
|
93
108
|
raise TypeError unless spec.is_a?(InstanceSpec)
|
94
109
|
inst_on_hp = self.instances_dataset.lives.all
|
95
110
|
|
96
|
-
(self.offering_cpu_cores
|
97
|
-
(self.offering_memory_size
|
111
|
+
(self.offering_cpu_cores >= inst_on_hp.inject(0) {|t, i| t += i.cpu_cores } + spec.cpu_cores) &&
|
112
|
+
(self.offering_memory_size >= inst_on_hp.inject(0) {|t, i| t += i.memory_size } + spec.memory_size)
|
98
113
|
end
|
99
114
|
|
115
|
+
def to_api_document
|
116
|
+
h = to_hash
|
117
|
+
h.delete(:node_id)
|
118
|
+
h
|
119
|
+
end
|
100
120
|
|
101
121
|
end
|
102
122
|
end
|
data/lib/dcmgr/models/image.rb
CHANGED
@@ -14,17 +14,19 @@ module Dcmgr::Models
|
|
14
14
|
Text :source, :null=>false
|
15
15
|
String :arch, :size=>10, :null=>false
|
16
16
|
Text :description
|
17
|
+
Boolean :is_public, :null=>false, :default=>false
|
17
18
|
#Fixnum :parent_image_id
|
19
|
+
String :format, :null=>false, :default=>'raw'
|
18
20
|
|
19
21
|
String :state, :size=>20, :null=>false, :default=>:init.to_s
|
22
|
+
index :is_public
|
20
23
|
end
|
21
24
|
|
22
25
|
# serialize plugin must be defined at the bottom of all class
|
23
26
|
# method calls.
|
24
27
|
# Possible source column data:
|
25
|
-
#
|
26
|
-
# {:
|
27
|
-
# {:type=>:http, :uri=>'http://localhost/xxx/xxx'}
|
28
|
+
# {:snapshot_id=>'snap-xxxxxx'}
|
29
|
+
# {:uri=>'http://localhost/xxx/xxx'}
|
28
30
|
plugin :serialization
|
29
31
|
serialize_attributes :yaml, :source
|
30
32
|
|
@@ -36,11 +38,37 @@ module Dcmgr::Models
|
|
36
38
|
unless HostPool::SUPPORTED_ARCH.member?(self.arch)
|
37
39
|
errors.add(:arch, "Unsupported arch type: #{self.arch}")
|
38
40
|
end
|
41
|
+
|
42
|
+
# validate source
|
43
|
+
md = self.source
|
44
|
+
case self.boot_dev_type
|
45
|
+
when BOOT_DEV_LOCAL
|
46
|
+
errors.add(:source, "Unknown image URI") if md[:uri].nil? || md[:uri] == ''
|
47
|
+
when BOOT_DEV_SAN
|
48
|
+
errors.add(:source, "Unknown snapshot ID") if md[:snapshot_id].nil? || md[:snapshot_id] == '' || VolumeSnapshot[md[:snapshot_id]].nil?
|
49
|
+
end
|
39
50
|
end
|
40
51
|
|
41
52
|
def to_hash
|
42
53
|
super.merge({:source=>self.source.dup, :description=>description.to_s})
|
43
54
|
end
|
55
|
+
|
56
|
+
# note on "lookup_account_id":
|
57
|
+
# the source column sometime contains the information which
|
58
|
+
# should not be shown to other accounts. so that the method takes
|
59
|
+
# an argument who is looking into then filters the data in source
|
60
|
+
# column accordingly.
|
61
|
+
def to_api_document(lookup_account_id)
|
62
|
+
h = to_hash
|
63
|
+
if self.account_id == lookup_account_id
|
64
|
+
else
|
65
|
+
if h[:source][:type] == :http
|
66
|
+
# do not show URI for non-owner accounts.
|
67
|
+
h[:source][:uri] = nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
h
|
71
|
+
end
|
44
72
|
|
45
73
|
end
|
46
74
|
end
|
@@ -17,11 +17,16 @@ module Dcmgr::Models
|
|
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
19
|
String :hostname, :null=>false, :size=>32
|
20
|
+
# TODO: remove ssh_key_pair_id column
|
20
21
|
String :ssh_key_pair_id
|
21
22
|
Fixnum :ha_enabled, :null=>false, :default=>0
|
23
|
+
Float :quota_weight, :null=>false, :default=>0.0
|
24
|
+
Fixnum :cpu_cores, :null=>false, :unsigned=>true
|
25
|
+
Fixnum :memory_size, :null=>false, :unsigned=>true
|
22
26
|
|
23
27
|
Text :user_data, :null=>false, :default=>''
|
24
28
|
Text :runtime_config, :null=>false, :default=>''
|
29
|
+
Text :ssh_key_data, :null=>true
|
25
30
|
|
26
31
|
Time :terminated_at
|
27
32
|
index :state
|
@@ -36,13 +41,22 @@ module Dcmgr::Models
|
|
36
41
|
one_to_many :volume
|
37
42
|
one_to_many :instance_nic
|
38
43
|
alias :nic :instance_nic
|
39
|
-
one_to_many :instance_netfilter_groups
|
40
44
|
many_to_many :netfilter_groups, :join_table=>:instance_netfilter_groups
|
45
|
+
# TODO: remove ssh_key_pair_id column
|
41
46
|
many_to_one :ssh_key_pair
|
42
47
|
|
43
48
|
plugin ArchiveChangedColumn, :histories
|
44
49
|
|
45
50
|
subset(:lives, {:terminated_at => nil})
|
51
|
+
|
52
|
+
RECENT_TERMED_PERIOD=(60 * 15)
|
53
|
+
# lists the instances which alives and died within
|
54
|
+
# RECENT_TERMED_PERIOD sec.
|
55
|
+
# it was difficult for me to write exprs in virtual row syntax as
|
56
|
+
# per subset(). ;-(
|
57
|
+
def_dataset_method(:alives_and_recent_termed) {
|
58
|
+
filter("terminated_at IS NULL OR terminated_at >= ?", (Time.now.utc - RECENT_TERMED_PERIOD))
|
59
|
+
}
|
46
60
|
|
47
61
|
# serialization plugin must be defined at the bottom of all class
|
48
62
|
# method calls.
|
@@ -51,6 +65,8 @@ module Dcmgr::Models
|
|
51
65
|
# {:vnc_port=>11, :telnet_port=>1111}
|
52
66
|
plugin :serialization
|
53
67
|
serialize_attributes :yaml, :runtime_config
|
68
|
+
# equal to SshKeyPair#to_hash
|
69
|
+
serialize_attributes :yaml, :ssh_key_data
|
54
70
|
|
55
71
|
module ValidationMethods
|
56
72
|
def self.hostname_uniqueness(account_id, hostname)
|
@@ -125,14 +141,20 @@ module Dcmgr::Models
|
|
125
141
|
end
|
126
142
|
@update_hostname = false
|
127
143
|
end
|
128
|
-
|
144
|
+
|
145
|
+
# sum() returns nil if there is no instance rows.
|
146
|
+
lives_weight = self.class.filter(:account_id=>self.account_id).lives.sum(:quota_weight) || 0.0
|
147
|
+
unless lives_weight <= self.account.quota.instance_total_weight
|
148
|
+
raise "Out of quota limit: #{self.account_id}'s current weight capacity: #{lives_weight} (<= #{self.account.quota.instance_total_weight})"
|
149
|
+
end
|
150
|
+
|
129
151
|
super
|
130
152
|
end
|
131
153
|
|
132
154
|
def before_destroy
|
133
155
|
HostnameLease.filter(:account_id=>self.account_id, :hostname=>self.hostname).destroy
|
134
156
|
self.instance_nic.each { |o| o.destroy }
|
135
|
-
self.
|
157
|
+
self.remove_all_netfilter_groups
|
136
158
|
self.volume.each { |v|
|
137
159
|
v.instance_id = nil
|
138
160
|
v.state = :available
|
@@ -154,14 +176,15 @@ module Dcmgr::Models
|
|
154
176
|
# this is for internal use.
|
155
177
|
def to_hash
|
156
178
|
h = super
|
157
|
-
h
|
179
|
+
h.merge!({:user_data => user_data.to_s, # Sequel::BLOB -> String
|
158
180
|
:runtime_config => self.runtime_config, # yaml -> hash
|
159
181
|
:image=>image.to_hash,
|
160
182
|
:host_pool=>host_pool.to_hash,
|
161
183
|
:instance_nics=>instance_nic.map {|n| n.to_hash },
|
162
|
-
:
|
163
|
-
:
|
164
|
-
|
184
|
+
:ips => instance_nic.map { |n| n.ip.map {|i| unless i.is_natted? then i.ipv4 else nil end} if n.ip }.flatten.compact,
|
185
|
+
:nat_ips => instance_nic.map { |n| n.ip.map {|i| if i.is_natted? then i.ipv4 else nil end} if n.ip }.flatten.compact,
|
186
|
+
})
|
187
|
+
h.merge!({:instance_spec=>instance_spec.to_hash}) unless instance_spec.nil?
|
165
188
|
h[:volume]={}
|
166
189
|
if self.volume
|
167
190
|
self.volume.each { |v|
|
@@ -186,12 +209,13 @@ module Dcmgr::Models
|
|
186
209
|
# :created_at
|
187
210
|
# :state
|
188
211
|
# :status
|
212
|
+
# :vif => {'vif-xxxxx'=>{:ipv4=>{:address=>'8.8.8.8', :nat_address=>'9.9.9.9.9'}}}
|
189
213
|
# }
|
190
214
|
def to_api_document
|
191
215
|
h = {
|
192
216
|
:id => canonical_uuid,
|
193
|
-
:cpu_cores =>
|
194
|
-
:memory_size =>
|
217
|
+
:cpu_cores => cpu_cores,
|
218
|
+
:memory_size => memory_size,
|
195
219
|
:image_id => image.canonical_uuid,
|
196
220
|
:created_at => self.created_at,
|
197
221
|
:state => self.state,
|
@@ -200,19 +224,41 @@ module Dcmgr::Models
|
|
200
224
|
:network => [],
|
201
225
|
:volume => [],
|
202
226
|
:netfilter_group => [],
|
227
|
+
:vif => [],
|
203
228
|
}
|
204
|
-
if self.
|
205
|
-
h[:ssh_key_pair] = self.
|
229
|
+
if self.ssh_key_data
|
230
|
+
h[:ssh_key_pair] = self.ssh_key_data[:name]
|
206
231
|
end
|
207
232
|
|
208
233
|
if instance_nic
|
209
234
|
instance_nic.each { |n|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
235
|
+
direct_lease_ds = n.direct_ip_lease_dataset
|
236
|
+
next if direct_lease_ds.first.nil?
|
237
|
+
outside_lease_ds = n.nat_ip_lease_dataset
|
238
|
+
|
239
|
+
h[:network] << {
|
240
|
+
:network_name => n.network.canonical_uuid,
|
241
|
+
:ipaddr => direct_lease_ds.all.map {|lease| lease.ipv4 }.compact,
|
242
|
+
:nat_ipaddr => outside_lease_ds.all.map {|lease| lease.ipv4 }.compact
|
243
|
+
}
|
244
|
+
}
|
245
|
+
end
|
246
|
+
|
247
|
+
if instance_nic
|
248
|
+
instance_nic.each { |vif|
|
249
|
+
ent = {
|
250
|
+
:vif_id=>vif.canonical_uuid,
|
251
|
+
}
|
252
|
+
direct_lease = vif.direct_ip_lease.first
|
253
|
+
if direct_lease.nil?
|
254
|
+
else
|
255
|
+
outside_lease = direct_lease.nat_outside_lease
|
256
|
+
ent[:ipv4] = {
|
257
|
+
:address=> direct_lease.ipv4,
|
258
|
+
:nat_address => outside_lease.nil? ? nil : outside_lease.ipv4,
|
214
259
|
}
|
215
260
|
end
|
261
|
+
h[:vif] << ent
|
216
262
|
}
|
217
263
|
end
|
218
264
|
|
@@ -244,14 +290,6 @@ module Dcmgr::Models
|
|
244
290
|
self.image.arch
|
245
291
|
end
|
246
292
|
|
247
|
-
def cpu_cores
|
248
|
-
self.instance_spec.cpu_cores
|
249
|
-
end
|
250
|
-
|
251
|
-
def memory_size
|
252
|
-
self.instance_spec.memory_size
|
253
|
-
end
|
254
|
-
|
255
293
|
def config
|
256
294
|
self.instance_spec.config
|
257
295
|
end
|
@@ -261,6 +299,7 @@ module Dcmgr::Models
|
|
261
299
|
vendor_id ||= '00:ff:f1'
|
262
300
|
nic = InstanceNic.new(:mac_addr=>vendor_id)
|
263
301
|
nic.network = network
|
302
|
+
nic.nat_network = network.nat_network
|
264
303
|
nic.instance = self
|
265
304
|
nic.save
|
266
305
|
end
|
@@ -335,10 +374,20 @@ module Dcmgr::Models
|
|
335
374
|
Volume.lock!
|
336
375
|
VolumeSnapshot.lock!
|
337
376
|
IpLease.lock!
|
377
|
+
HostnameLease.lock!
|
378
|
+
Network.lock!
|
338
379
|
end
|
339
380
|
|
340
381
|
def live?
|
341
382
|
self.terminated_at.nil?
|
342
383
|
end
|
384
|
+
|
385
|
+
def set_ssh_key_pair(ssh_key_pair)
|
386
|
+
raise ArgumentError unless ssh_key_pair.is_a?(SshKeyPair)
|
387
|
+
self.ssh_key_data = ssh_key_pair.to_hash
|
388
|
+
# TODO: remove ssh_key_pair_id column
|
389
|
+
self.ssh_key_pair_id = ssh_key_pair.canonical_uuid
|
390
|
+
end
|
391
|
+
|
343
392
|
end
|
344
393
|
end
|