wakame-vdc-dcmgr 11.06.0 → 11.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. data/Rakefile +19 -31
  2. data/bin/collector +6 -1
  3. data/config/db/migrations/0001_v1110_origin.rb +446 -0
  4. data/config/dcmgr.conf.example +51 -0
  5. data/lib/dcmgr.rb +99 -22
  6. data/lib/dcmgr/cli/base.rb +34 -1
  7. data/lib/dcmgr/cli/host.rb +24 -20
  8. data/lib/dcmgr/cli/image.rb +38 -19
  9. data/lib/dcmgr/cli/keypair.rb +16 -12
  10. data/lib/dcmgr/cli/network.rb +189 -81
  11. data/lib/dcmgr/cli/quota.rb +2 -2
  12. data/lib/dcmgr/cli/security_group.rb +106 -0
  13. data/lib/dcmgr/cli/spec.rb +144 -39
  14. data/lib/dcmgr/cli/storage.rb +16 -15
  15. data/lib/dcmgr/cli/tag.rb +20 -14
  16. data/lib/dcmgr/cli/vlan.rb +5 -5
  17. data/lib/dcmgr/drivers/backing_store.rb +32 -0
  18. data/lib/dcmgr/drivers/comstar.rb +81 -0
  19. data/lib/dcmgr/drivers/iijgio_storage.rb +9 -19
  20. data/lib/dcmgr/drivers/iscsi_target.rb +41 -0
  21. data/lib/dcmgr/drivers/kvm.rb +161 -28
  22. data/lib/dcmgr/drivers/linux_iscsi.rb +60 -0
  23. data/lib/dcmgr/drivers/local_storage.rb +24 -0
  24. data/lib/dcmgr/drivers/lxc.rb +167 -125
  25. data/lib/dcmgr/drivers/raw.rb +74 -0
  26. data/lib/dcmgr/drivers/s3_storage.rb +7 -19
  27. data/lib/dcmgr/drivers/snapshot_storage.rb +18 -28
  28. data/lib/dcmgr/drivers/storage_initiator.rb +28 -0
  29. data/lib/dcmgr/drivers/sun_iscsi.rb +32 -0
  30. data/lib/dcmgr/drivers/zfs.rb +77 -0
  31. data/lib/dcmgr/endpoints/core_api.rb +315 -263
  32. data/lib/dcmgr/endpoints/errors.rb +21 -10
  33. data/lib/dcmgr/endpoints/metadata.rb +360 -23
  34. data/lib/dcmgr/helpers/cli_helper.rb +6 -3
  35. data/lib/dcmgr/helpers/ec2_metadata_helper.rb +9 -0
  36. data/lib/dcmgr/helpers/nic_helper.rb +11 -0
  37. data/lib/dcmgr/helpers/snapshot_storage_helper.rb +34 -0
  38. data/lib/dcmgr/models/account.rb +0 -6
  39. data/lib/dcmgr/models/account_resource.rb +0 -4
  40. data/lib/dcmgr/models/base_new.rb +14 -2
  41. data/lib/dcmgr/models/dhcp_range.rb +38 -0
  42. data/lib/dcmgr/models/frontend_system.rb +0 -6
  43. data/lib/dcmgr/models/history.rb +0 -11
  44. data/lib/dcmgr/models/host_node.rb +131 -0
  45. data/lib/dcmgr/models/hostname_lease.rb +0 -8
  46. data/lib/dcmgr/models/image.rb +31 -18
  47. data/lib/dcmgr/models/instance.rb +137 -143
  48. data/lib/dcmgr/models/instance_nic.rb +52 -29
  49. data/lib/dcmgr/models/instance_security_group.rb +9 -0
  50. data/lib/dcmgr/models/instance_spec.rb +163 -31
  51. data/lib/dcmgr/models/ip_lease.rb +10 -21
  52. data/lib/dcmgr/models/mac_lease.rb +30 -11
  53. data/lib/dcmgr/models/network.rb +148 -27
  54. data/lib/dcmgr/models/physical_network.rb +18 -0
  55. data/lib/dcmgr/models/quota.rb +0 -10
  56. data/lib/dcmgr/models/request_log.rb +3 -18
  57. data/lib/dcmgr/models/security_group.rb +66 -0
  58. data/lib/dcmgr/models/security_group_rule.rb +145 -0
  59. data/lib/dcmgr/models/ssh_key_pair.rb +16 -19
  60. data/lib/dcmgr/models/{storage_pool.rb → storage_node.rb} +35 -25
  61. data/lib/dcmgr/models/tag.rb +0 -14
  62. data/lib/dcmgr/models/tag_mapping.rb +1 -7
  63. data/lib/dcmgr/models/vlan_lease.rb +2 -8
  64. data/lib/dcmgr/models/volume.rb +49 -37
  65. data/lib/dcmgr/models/volume_snapshot.rb +15 -17
  66. data/lib/dcmgr/node_modules/hva_collector.rb +69 -28
  67. data/lib/dcmgr/node_modules/instance_ha.rb +23 -12
  68. data/lib/dcmgr/node_modules/instance_monitor.rb +16 -2
  69. data/lib/dcmgr/node_modules/openflow_controller.rb +784 -0
  70. data/lib/dcmgr/node_modules/scheduler.rb +189 -0
  71. data/lib/dcmgr/node_modules/service_netfilter.rb +452 -227
  72. data/lib/dcmgr/node_modules/service_openflow.rb +731 -0
  73. data/lib/dcmgr/node_modules/sta_collector.rb +20 -0
  74. data/lib/dcmgr/node_modules/sta_tgt_initializer.rb +35 -0
  75. data/lib/dcmgr/rack/request_logger.rb +11 -6
  76. data/lib/dcmgr/rpc/hva_handler.rb +256 -110
  77. data/lib/dcmgr/rpc/sta_handler.rb +244 -0
  78. data/lib/dcmgr/scheduler.rb +122 -8
  79. data/lib/dcmgr/scheduler/host_node/exclude_same.rb +24 -0
  80. data/lib/dcmgr/scheduler/host_node/find_first.rb +12 -0
  81. data/lib/dcmgr/scheduler/host_node/least_usage.rb +28 -0
  82. data/lib/dcmgr/scheduler/host_node/per_instance.rb +18 -0
  83. data/lib/dcmgr/scheduler/host_node/specify_node.rb +26 -0
  84. data/lib/dcmgr/scheduler/network/flat_single.rb +23 -0
  85. data/lib/dcmgr/scheduler/network/nat_one_to_one.rb +23 -0
  86. data/lib/dcmgr/scheduler/network/per_instance.rb +39 -0
  87. data/lib/dcmgr/scheduler/network/vif_template.rb +19 -0
  88. data/lib/dcmgr/scheduler/storage_node/find_first.rb +13 -0
  89. data/lib/dcmgr/scheduler/storage_node/least_usage.rb +23 -0
  90. data/lib/dcmgr/storage_service.rb +39 -40
  91. data/lib/dcmgr/tags.rb +3 -3
  92. data/lib/dcmgr/version.rb +1 -1
  93. data/lib/dcmgr/vnet.rb +105 -0
  94. data/lib/dcmgr/vnet/factories.rb +141 -0
  95. data/lib/dcmgr/vnet/isolators/by_securitygroup.rb +21 -0
  96. data/lib/dcmgr/vnet/isolators/dummy.rb +17 -0
  97. data/lib/dcmgr/vnet/netfilter/cache.rb +51 -0
  98. data/lib/dcmgr/vnet/netfilter/chain.rb +66 -0
  99. data/lib/dcmgr/vnet/netfilter/controller.rb +193 -0
  100. data/lib/dcmgr/vnet/netfilter/ebtables_rule.rb +53 -0
  101. data/lib/dcmgr/vnet/netfilter/iptables_rule.rb +45 -0
  102. data/lib/dcmgr/vnet/netfilter/task_manager.rb +459 -0
  103. data/lib/dcmgr/vnet/tasks/accept_all_dns.rb +19 -0
  104. data/lib/dcmgr/vnet/tasks/accept_arp_broadcast.rb +24 -0
  105. data/lib/dcmgr/vnet/tasks/accept_arp_from_friends.rb +34 -0
  106. data/lib/dcmgr/vnet/tasks/accept_arp_from_gateway.rb +21 -0
  107. data/lib/dcmgr/vnet/tasks/accept_arp_to_host.rb +30 -0
  108. data/lib/dcmgr/vnet/tasks/accept_ip_from_friends.rb +26 -0
  109. data/lib/dcmgr/vnet/tasks/accept_ip_from_gateway.rb +23 -0
  110. data/lib/dcmgr/vnet/tasks/accept_ip_to_anywhere.rb +18 -0
  111. data/lib/dcmgr/vnet/tasks/accept_related_established.rb +45 -0
  112. data/lib/dcmgr/vnet/tasks/accept_wakame_dhcp_only.rb +33 -0
  113. data/lib/dcmgr/vnet/tasks/accept_wakame_dns_only.rb +33 -0
  114. data/lib/dcmgr/vnet/tasks/debug_iptables.rb +21 -0
  115. data/lib/dcmgr/vnet/tasks/drop_arp_forwarding.rb +27 -0
  116. data/lib/dcmgr/vnet/tasks/drop_arp_to_host.rb +24 -0
  117. data/lib/dcmgr/vnet/tasks/drop_ip_from_anywhere.rb +18 -0
  118. data/lib/dcmgr/vnet/tasks/drop_ip_spoofing.rb +34 -0
  119. data/lib/dcmgr/vnet/tasks/drop_mac_spoofing.rb +33 -0
  120. data/lib/dcmgr/vnet/tasks/exclude_from_nat.rb +47 -0
  121. data/lib/dcmgr/vnet/tasks/security_group.rb +37 -0
  122. data/lib/dcmgr/vnet/tasks/static_nat.rb +54 -0
  123. data/lib/dcmgr/vnet/tasks/translate_metadata_address.rb +32 -0
  124. data/web/metadata/config.ru +1 -1
  125. metadata +174 -89
  126. data/lib/dcmgr/cli/group.rb +0 -101
  127. data/lib/dcmgr/endpoints/core_api_mock.rb +0 -865
  128. data/lib/dcmgr/models/host_pool.rb +0 -122
  129. data/lib/dcmgr/models/instance_netfilter_group.rb +0 -16
  130. data/lib/dcmgr/models/netfilter_group.rb +0 -89
  131. data/lib/dcmgr/models/netfilter_rule.rb +0 -21
  132. data/lib/dcmgr/scheduler/find_last.rb +0 -16
  133. data/lib/dcmgr/scheduler/find_random.rb +0 -16
  134. data/lib/dcmgr/stm/instance.rb +0 -25
  135. data/lib/dcmgr/stm/snapshot_context.rb +0 -33
  136. data/lib/dcmgr/stm/volume_context.rb +0 -65
@@ -16,9 +16,13 @@ module Dcmgr
16
16
 
17
17
  timersig = EventMachine.add_timer(opts[:timeout]) {
18
18
  timedout = true
19
- if curthread
19
+ if curthread && curthread.alive?
20
20
  curthread.raise(TimeoutError.new("timeout"))
21
- curthread.pass
21
+ begin
22
+ curthread.pass
23
+ rescue ::Exception => e
24
+ # any thread errors can be ignored.
25
+ end
22
26
  end
23
27
  }
24
28
 
@@ -35,7 +39,6 @@ module Dcmgr
35
39
  end
36
40
  retry if (count -= 1) >= 0
37
41
  ensure
38
- curthread = nil
39
42
  EventMachine.cancel_timer(timersig) rescue nil
40
43
  end
41
44
  end
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Dcmgr
4
+ module Helpers
5
+ module Ec2MetadataHelper
6
+
7
+ end
8
+ end
9
+ end
@@ -20,6 +20,17 @@ module Dcmgr
20
20
  File.readlines(operstate_path).first.strip
21
21
  end
22
22
  end
23
+
24
+ # This method cleans up ugly mac addressed stored in the dcmgr database.
25
+ # Mac addresses in the database are stored as alphanumeric strings without
26
+ # the : inbetween them. This method properly puts those in there.
27
+ def clean_mac(mac,delim = ':')
28
+ mac.unpack('A2'*6).join(delim)
29
+ end
30
+
31
+ def is_natted?(vnic_map)
32
+ not vnic_map[:ipv4][:nat_address].nil?
33
+ end
23
34
 
24
35
  def valid_nic?(nic)
25
36
  ifindex_path = "/sys/class/net/#{nic}/ifindex"
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'rexml/document'
3
+
4
+ module Dcmgr
5
+ module Helpers
6
+ module SnapshotStorageHelper
7
+
8
+ def key(filename)
9
+ File.join(@account_id, filename)
10
+ end
11
+
12
+ def execute(cmd, args)
13
+ script_root_path = File.join(File.expand_path('../../../../',__FILE__), 'script')
14
+ script = File.join(script_root_path, 'storage_service')
15
+ cmd = "/usr/bin/env #{@env.join(' ')} %s " + cmd
16
+ args = [script] + args
17
+ res = sh(cmd, args)
18
+
19
+ if res[:stdout] != ''
20
+ doc = REXML::Document.new res[:stdout]
21
+ code = REXML::XPath.match( doc, "//Error/Code/text()" ).to_s
22
+ message = REXML::XPath.match( doc, "//Error/Message/text()" ).to_s
23
+ bucket_name = REXML::XPath.match( doc, "//Error/BucketName/text()" ).to_s
24
+ request_id = REXML::XPath.match( doc, "//Error/RequestId/text()" ).to_s
25
+ host_id = REXML::XPath.match( doc, "//Error/HostId/text()" ).to_s
26
+ error_message = ["Snapshot execute error: ",cmd, code, message, bucket_name, request_id, host_id].join(',')
27
+ raise error_message
28
+ else
29
+ res
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -9,12 +9,6 @@ module Dcmgr::Models
9
9
  DISABLED=0
10
10
  ENABLED=1
11
11
 
12
- inheritable_schema do
13
- String :description, :size=>100
14
- Fixnum :enabled, :default=>ENABLED, :null=>false
15
- end
16
- with_timestamps
17
-
18
12
  one_to_many :tags, :dataset=>lambda { Tag.filter(:account_id=>self.canonical_uuid); }
19
13
  one_to_one :quota, :class=>Quota, :key=>:account_id
20
14
 
@@ -4,10 +4,6 @@ module Dcmgr::Models
4
4
  # Base class for the model class which belongs to a specific account.
5
5
  class AccountResource < BaseNew
6
6
 
7
- inheritable_schema do
8
- String :account_id, :null=>false, :index=>true
9
- end
10
-
11
7
  def account
12
8
  Account[self.account_id]
13
9
  end
@@ -131,7 +131,13 @@ module Dcmgr::Models
131
131
  end
132
132
 
133
133
  def to_hash()
134
- self.values.dup.merge({:id=>canonical_uuid, :uuid=>canonical_uuid})
134
+ self.values.dup.merge({:id=>self.id, :uuid=>canonical_uuid})
135
+ end
136
+
137
+ # generate API response document. similar to to_hash() but not
138
+ # to expose integer primary key.
139
+ def to_api_document
140
+ self.values.dup.merge({:id=>self.canonical_uuid, :uuid=>canonical_uuid})
135
141
  end
136
142
  end
137
143
 
@@ -186,7 +192,7 @@ module Dcmgr::Models
186
192
 
187
193
  # Checks the general uuid syntax
188
194
  def check_trimmed_uuid_format(uuid)
189
- uuid.match(/^[a-z0-9 ]*$/) && uuid.length <= 8
195
+ uuid.match(/^[a-z0-9]*$/) && uuid.length <= 255
190
196
  end
191
197
 
192
198
  # Checks the uuid syntax if it is for the Taggable class.
@@ -398,6 +404,10 @@ module Dcmgr::Models
398
404
 
399
405
  class BaseNew < Sequel::Model
400
406
 
407
+ def to_hash()
408
+ self.values.dup
409
+ end
410
+
401
411
  LOCK_TABLES_KEY='__locked_tables'
402
412
 
403
413
  def self.default_row_lock_mode=(mode)
@@ -479,8 +489,10 @@ module Dcmgr::Models
479
489
  private
480
490
  def self.inherited(klass)
481
491
  super
492
+ klass.set_dataset(db[klass.implicit_table_name])
482
493
 
483
494
  klass.plugin InheritableSchema
495
+ klass.plugin :timestamps, :update_on_create=>true
484
496
  klass.class_eval {
485
497
 
486
498
  # Add timestamp columns and set callbacks using Timestamps
@@ -0,0 +1,38 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'ipaddress'
4
+
5
+ module Dcmgr::Models
6
+ # Dynamic IP address range in the network.
7
+ class DhcpRange < BaseNew
8
+
9
+ many_to_one :network
10
+
11
+ def validate
12
+ super
13
+
14
+ if !self.network.ipv4_ipaddress.include?(self.range_begin)
15
+ errors.add(:range_begin, "Out of subnet range: #{self.range_begin}")
16
+ end
17
+
18
+ if !self.network.ipv4_ipaddress.include?(self.range_end)
19
+ errors.add(:range_end, "Out of subnet range: #{self.range_end}")
20
+ end
21
+
22
+ if !(self.range_begin <= self.range_end)
23
+ # swap values.
24
+ t = self[:range_end]
25
+ self[:range_end] = self[:range_begin]
26
+ self[:range_begin] = t
27
+ end
28
+ end
29
+
30
+ def range_begin
31
+ IPAddress::IPv4.new("#{super}/#{network.prefix}")
32
+ end
33
+
34
+ def range_end
35
+ IPAddress::IPv4.new("#{super}/#{network.prefix}")
36
+ end
37
+ end
38
+ end
@@ -5,12 +5,6 @@ module Dcmgr::Models
5
5
 
6
6
  plugin :single_table_inheritance, :kind
7
7
 
8
- inheritable_schema do
9
- String :kind, :null=>false
10
- String :key, :null=>false, :size=>40, :unique=>true
11
- String :credential
12
- end
13
-
14
8
  def authenticate
15
9
  raise NotImplementedError
16
10
  end
@@ -3,17 +3,6 @@
3
3
  module Dcmgr::Models
4
4
  # History record table for ArchiveChangedColumn plugin
5
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
6
 
18
7
  plugin :timestamps
19
8
 
@@ -0,0 +1,131 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'isono/models/node_state'
4
+
5
+ module Dcmgr::Models
6
+ class HostNode < AccountResource
7
+ taggable 'hn'
8
+
9
+ HYPERVISOR_XEN_34='xen-3.4'
10
+ HYPERVISOR_XEN_40='xen-4.0'
11
+ HYPERVISOR_KVM='kvm'
12
+ HYPERVISOR_LXC='lxc'
13
+
14
+ ARCH_X86=:x86.to_s
15
+ ARCH_X86_64=:x86_64.to_s
16
+
17
+ SUPPORTED_ARCH=[ARCH_X86, ARCH_X86_64]
18
+ SUPPORTED_HYPERVISOR=[HYPERVISOR_KVM, HYPERVISOR_LXC]
19
+
20
+ one_to_many :instances
21
+ many_to_one :node, :class=>Isono::Models::NodeState, :key=>:node_id, :primary_key=>:node_id
22
+
23
+ def_dataset_method(:online_nodes) do
24
+ # SELECT * FROM `host_nodes` WHERE ('node_id' IN (SELECT `node_id` FROM `node_states` WHERE (`state` = 'online')))
25
+ r = Isono::Models::NodeState.filter(:state => 'online').select(:node_id)
26
+ filter(:node_id => r)
27
+ end
28
+
29
+ def validate
30
+ super
31
+ # for compatibility: hva.xxx or hva-xxxx
32
+ unless self.node_id =~ /^hva[-.]/
33
+ errors.add(:node_id, "is invalid ID: #{self.node_id}")
34
+ end
35
+
36
+ if (h = self.class.filter(:node_id=>self.node_id).first) && h.id != self.id
37
+ errors.add(:node_id, " #{self.node_id} is already been associated to #{h.canonical_uuid} ")
38
+ end
39
+
40
+ unless SUPPORTED_ARCH.member?(self.arch)
41
+ errors.add(:arch, "unknown architecture type: #{self.arch}")
42
+ end
43
+
44
+ unless self.offering_cpu_cores > 0
45
+ errors.add(:offering_cpu_cores, "it must have digit more than zero")
46
+ end
47
+ unless self.offering_memory_size > 0
48
+ errors.add(:offering_memory_size, "it must have digit more than zero")
49
+ end
50
+ end
51
+
52
+ def to_hash
53
+ super.merge(:status=>self.status)
54
+ end
55
+
56
+ # Check if the resources exist depending on the HostNode.
57
+ # @return [boolean]
58
+ def depend_resources?
59
+ !self.instances_dataset.runnings.empty?
60
+ end
61
+
62
+ def status
63
+ node.nil? ? :offline : node.state
64
+ end
65
+
66
+ # Returns true/false if the host pool has enough capacity to run the spec.
67
+ # @param [InstanceSpec] spec
68
+ def check_capacity(spec)
69
+ raise TypeError unless spec.is_a?(InstanceSpec)
70
+ inst_on_hp = self.instances_dataset.lives.all
71
+
72
+ (self.offering_cpu_cores >= inst_on_hp.inject(0) {|t, i| t += i.cpu_cores } + spec.cpu_cores) &&
73
+ (self.offering_memory_size >= inst_on_hp.inject(0) {|t, i| t += i.memory_size } + spec.memory_size)
74
+ end
75
+
76
+ def to_api_document
77
+ h = super()
78
+ h.merge!(:status=>self.status)
79
+ h.delete(:node_id)
80
+ h
81
+ end
82
+
83
+ # Returns reserved CPU cores used by running/scheduled instances.
84
+ def cpu_core_usage
85
+ instances_usage(:cpu_cores)
86
+ end
87
+
88
+ # Returns reserved memory size used by running/scheduled instances.
89
+ def memory_size_usage
90
+ instances_usage(:memory_size)
91
+ end
92
+
93
+ # Returns available CPU cores.
94
+ def available_cpu_cores
95
+ self.offering_cpu_cores - self.cpu_core_usage
96
+ end
97
+
98
+ # Returns available memory size.
99
+ def available_memory_size
100
+ self.offering_memory_size - self.memory_size_usage
101
+ end
102
+
103
+ # Check the free resource capacity across entire local VDC domain.
104
+ def self.check_domain_capacity?(cpu_cores, memory_size, num=1)
105
+ alives_mem_size = Instance.dataset.lives.filter.sum(:memory_size).to_i
106
+ stopped_mem_size = Instance.dataset.lives.filter(:state=>'stopped').sum(:memory_size).to_i
107
+ alives_cpu_cores = Instance.dataset.lives.filter.sum(:cpu_cores).to_i
108
+ stopped_cpu_cores = Instance.dataset.lives.filter(:state=>'stopped').sum(:cpu_cores).to_i
109
+ # instance releases the resources during stopped state normally. however admins may
110
+ # want to manage the reserved resource ratio for stopped
111
+ # instances. "stopped_instance_usage_factor" conf parameter allows its control.
112
+ #
113
+ # * stopped_instance_usage_factor == 1.0 means that 100% of
114
+ # resources are reserved for stopped instances. all of them will
115
+ # success to start up but utilization of host notes will be dropped.
116
+ # * stopped_instance_usage_factor == 0.5 means that 50% of
117
+ # resources for stopped instances are reserved and rest of 50%
118
+ # may fail to start again.
119
+ usage_factor = (Dcmgr.conf.stopped_instance_usage_factor || 1.0).to_f
120
+ avail_mem_size = self.online_nodes.sum(:offering_memory_size).to_i - ((alives_mem_size - stopped_mem_size) + (stopped_mem_size * usage_factor).floor)
121
+ avail_cpu_cores = self.online_nodes.sum(:offering_cpu_cores).to_i - ((alives_cpu_cores - stopped_cpu_cores) + (stopped_cpu_cores * usage_factor).floor)
122
+
123
+ (avail_mem_size >= memory_size * num.to_i) && (avail_cpu_cores >= cpu_cores * num.to_i)
124
+ end
125
+
126
+ protected
127
+ def instances_usage(colname)
128
+ instances_dataset.lives.sum(colname).to_i
129
+ end
130
+ end
131
+ end
@@ -3,13 +3,5 @@
3
3
  module Dcmgr::Models
4
4
  # hostname table for each instance to ensure uniqueness.
5
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
6
  end
15
7
  end
@@ -4,38 +4,33 @@ module Dcmgr::Models
4
4
  # Metadata catalogs for bootable image file.
5
5
  class Image < AccountResource
6
6
  taggable 'wmi'
7
- with_timestamps
8
7
 
9
8
  BOOT_DEV_SAN=1
10
9
  BOOT_DEV_LOCAL=2
11
10
 
12
- inheritable_schema do
13
- Fixnum :boot_dev_type, :null=>false, :default=>BOOT_DEV_SAN
14
- Text :source, :null=>false
15
- String :arch, :size=>10, :null=>false
16
- Text :description
17
- Boolean :is_public, :null=>false, :default=>false
18
- #Fixnum :parent_image_id
19
- String :format, :null=>false, :default=>'raw'
20
-
21
- String :state, :size=>20, :null=>false, :default=>:init.to_s
22
- index :is_public
23
- end
24
-
25
11
  # serialize plugin must be defined at the bottom of all class
26
12
  # method calls.
27
13
  # Possible source column data:
28
14
  # {:snapshot_id=>'snap-xxxxxx'}
29
15
  # {:uri=>'http://localhost/xxx/xxx'}
30
16
  plugin :serialization
31
- serialize_attributes :yaml, :source
17
+ serialize_attributes :yaml, :source, :features
32
18
 
19
+ def after_initialize
20
+ super
21
+ unless self.features.is_a?(Hash)
22
+ self.features = {}
23
+ end
24
+ end
25
+
33
26
  def validate
27
+ super
28
+
34
29
  unless [BOOT_DEV_SAN, BOOT_DEV_LOCAL].member?(self.boot_dev_type)
35
30
  errors.add(:boot_dev_type, "Invalid boot dev type: #{self.boot_dev_type}")
36
31
  end
37
32
 
38
- unless HostPool::SUPPORTED_ARCH.member?(self.arch)
33
+ unless HostNode::SUPPORTED_ARCH.member?(self.arch)
39
34
  errors.add(:arch, "Unsupported arch type: #{self.arch}")
40
35
  end
41
36
 
@@ -50,7 +45,7 @@ module Dcmgr::Models
50
45
  end
51
46
 
52
47
  def to_hash
53
- super.merge({:source=>self.source.dup, :description=>description.to_s})
48
+ super.merge({:source=>self.source, :description=>self.description.to_s, :features=>self.features})
54
49
  end
55
50
 
56
51
  # note on "lookup_account_id":
@@ -59,7 +54,7 @@ module Dcmgr::Models
59
54
  # an argument who is looking into then filters the data in source
60
55
  # column accordingly.
61
56
  def to_api_document(lookup_account_id)
62
- h = to_hash
57
+ h = super()
63
58
  if self.account_id == lookup_account_id
64
59
  else
65
60
  if h[:source][:type] == :http
@@ -69,6 +64,24 @@ module Dcmgr::Models
69
64
  end
70
65
  h
71
66
  end
67
+
68
+ # TODO: more proper key&value validation.
69
+ # Handles the feature blob column.
70
+ def set_feature(key, value)
71
+ case key.to_sym
72
+ when :virtio
73
+ self.features[:virtio] = value
74
+ else
75
+ raise "Unsupported feature: #{key}"
76
+ end
77
+
78
+ self.changed_columns << :features
79
+ self
80
+ end
81
+
82
+ def get_feature(key)
83
+ self.features[key]
84
+ end
72
85
 
73
86
  end
74
87
  end