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
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Dcmgr::Models
4
+ class InstanceSecurityGroup < BaseNew
5
+
6
+ many_to_one :instance
7
+ many_to_one :security_group
8
+ end
9
+ end
@@ -4,54 +4,186 @@ module Dcmgr::Models
4
4
  class InstanceSpec < AccountResource
5
5
  taggable 'is'
6
6
 
7
- inheritable_schema do
8
- String :name, :null=>false
9
- String :hypervisor, :null=>false
10
- String :arch, :null=>false
11
-
12
- Fixnum :cpu_cores, :null=>false, :unsigned=>true
13
- Fixnum :memory_size, :null=>false, :unsigned=>true
14
- Float :quota_weight, :null=>false, :default=>1.0
15
- Text :config, :null=>false, :default=>''
16
- Text :storage, :null=>false, :default=>''
17
-
18
- index [:account_id, :name], {:unique=>true}
19
- end
20
- with_timestamps
21
-
22
7
  # serialization plugin must be defined at the bottom of all class
23
8
  # method calls.
24
- # Possible column data:
25
- # hypervisor=kvm:
26
- # {:block_driver=>'virtio', :nic_driver=>'virtio'}
27
9
  plugin :serialization
28
10
  serialize_attributes :yaml, :config
29
- # hypervisor=kvm:
30
- # { 'sdc' => {:type=>:vdcvol, :size=>100, :dev=>'/dev/sdc'},
31
- # 'eph1' => {:type=>:ephemeral, :size=>1000, :dev=>'/dev/sdb'}}
32
- serialize_attributes :yaml, :storage
33
-
34
- def before_validate
35
- default_config =
36
- case self.hypervisor
37
- when HostPool::HYPERVISOR_KVM
38
- {:block_driver=>'virtio', :nic_driver=>'virtio'}
39
- end
11
+ # initial attached virtual interface definition:
12
+ # {
13
+ # 'vif1' => {
14
+ # :index => 0, # (>=0) required and unique
15
+ # :bandwidth=>512, # (kbps) required
16
+ # },
17
+ # 'vif2' => {
18
+ # :index => 10, # (>=0) required and unique
19
+ # :bandwidth=>50000, # (kbps) required
20
+ # },
21
+ # }
22
+ serialize_attributes :yaml, :vifs
23
+ # initial attached disk definition:
24
+ # {
25
+ # # blank disk image file on host OS for swap device.
26
+ # 'swap1' => {
27
+ # :index => 0, # (>=0) required and unique
28
+ # :type => :local, # required
29
+ # :size => 100, # (MB) required
30
+ # },
31
+ # # attach volume disk from snapshot.
32
+ # 'volume1' => {
33
+ # :index => 1, # (>=0) required and unique
34
+ # :type => :volume, # required
35
+ # :snapshot_id => 'snap-xxxxxx', # required
36
+ # },
37
+ # # attach blank volume disk.
38
+ # 'volume2' => {
39
+ # :index => 5, # (>=0) required and unique
40
+ # :type => :volume, # required
41
+ # :size => 100, # (MB) required
42
+ # },
43
+ # }
44
+ serialize_attributes :yaml, :drives
45
+
46
+ def before_validation
47
+ default_config = {}
40
48
 
41
49
  self.config = default_config.merge(self.config || {})
50
+
51
+ # Set empty hash for
52
+ self.vifs ||= {}
53
+ self.drives ||= {}
54
+ super
55
+ end
56
+
57
+ def validate
58
+ super
59
+
60
+ # uniquness check for :index
61
+ unless self.vifs.values.map {|i| i[:index] }.uniq.size == self.vifs.size
62
+ errors.add(:vifs, "duplicate index value.")
63
+ end
64
+ unless self.drives.values.map {|i| i[:index] }.uniq.size == self.drives.size
65
+ errors.add(:drives, "duplicate index value.")
66
+ end
67
+ end
68
+
69
+ def before_destroy
70
+ if !Instance.alives.filter(:instance_spec_id=>self.id).empty?
71
+ raise "There are one or more running instances refers this record."
72
+ end
73
+
42
74
  super
43
75
  end
44
76
 
45
77
  def to_hash
46
78
  super.merge({:config=>self.config, # yaml -> Hash
47
- :storage => self.storage, # yaml -> Hash
79
+ :vifs => self.vifs, # yaml -> Hash
80
+ :drives => self.drives, # yaml -> Hash
48
81
  })
49
82
  end
50
83
 
51
84
  def to_api_document
52
- doc = to_hash
85
+ doc = super()
53
86
  doc.delete(:config)
54
87
  doc
55
88
  end
89
+
90
+ # Modify methods for vifs,drives hash parameters.
91
+ def add_vif(name, index, bandwidth)
92
+ raise "Duplicate interface name: #{name}" if self.vifs.has_key?(name)
93
+ self.vifs[name]={
94
+ :index => index,
95
+ :bandwidth => bandwidth,
96
+ }
97
+ self.changed_columns << :vifs
98
+ self
99
+ end
100
+
101
+ def update_vif_index(name, new_index)
102
+ raise "Unknown interface name: #{name}" if !self.vifs.has_key?(name)
103
+ self.vifs[name][:index]=new_index
104
+ self.changed_columns << :vifs
105
+ self
106
+ end
107
+
108
+ def update_vif_bandwidth(name, bandwidth)
109
+ raise "Unknown interface name: #{name}" if !self.vifs.has_key?(name)
110
+ self.vifs[name][:bandwidth]=bandwidth
111
+ self.changed_columns << :vifs
112
+ self
113
+ end
114
+
115
+ def remove_vif(name)
116
+ self.vifs.delete(name)
117
+ self.changed_columns << :vifs
118
+ self
119
+ end
120
+
121
+ def add_local_drive(name, index, size)
122
+ raise "Duplicate drive name: #{name}" if self.drives.has_key?(name)
123
+ self.drives[name] = {
124
+ :index => index,
125
+ :type => :local,
126
+ :size => size,
127
+ }
128
+ self.changed_columns << :drives
129
+ self
130
+ end
131
+
132
+ def add_volume_drive(name, index, size)
133
+ raise "Duplicate drive name: #{name}" if self.drives.has_key?(name)
134
+ self.drives[name] = {
135
+ :index => index,
136
+ :type => :volume,
137
+ :size => size,
138
+ }
139
+ self.changed_columns << :drives
140
+ self
141
+ end
142
+
143
+ def add_volume_drive_from_snapshot(name, index, snapshot_id)
144
+ raise "Duplicate drive name: #{name}" if self.drives.has_key?(name)
145
+ self.drives[name] = {
146
+ :index => index,
147
+ :type => :volume,
148
+ :snapshot_id => snapshot_id,
149
+ }
150
+ self.changed_columns << :drives
151
+ self
152
+ end
153
+
154
+ def update_drive_index(name, new_index)
155
+ raise "Unknown drive name: #{name}" if !self.drives.has_key?(name)
156
+ drive = self.drives[name]
157
+ drive[:index] = new_index
158
+ self.changed_columns << :drives
159
+ self
160
+ end
161
+
162
+ def update_drive_snapshot_id(name, snapshot_id)
163
+ raise "Unknown drive name: #{name}" if !self.drives.has_key?(name)
164
+ drive = self.drives[name]
165
+ raise "Snapshot ID can only be set to volume drive" if !(drive[:type] == :volume)
166
+ drive.delete(:size)
167
+ # TODO: syntax check for snapshot_id
168
+ drive[:snapshot_id] = snapshot_id
169
+ self.changed_columns << :drives
170
+ self
171
+ end
172
+
173
+ def update_drive_size(name, size)
174
+ raise "Unknown drive name: #{name}" if !self.drives.has_key?(name)
175
+ drive = self.drives[name]
176
+ drive.delete(:snapshot_id) if drive[:type] == :volume
177
+ drive[:size] = size
178
+ self.changed_columns << :drives
179
+ self
180
+ end
181
+
182
+ def remove_drive(name)
183
+ self.drives.delete(name)
184
+ self.changed_columns << :drives
185
+ self
186
+ end
187
+
56
188
  end
57
189
  end
@@ -15,18 +15,6 @@ module Dcmgr::Models
15
15
  TYPE_MANUAL=>'manual'
16
16
  }
17
17
 
18
- inheritable_schema do
19
- Fixnum :instance_nic_id
20
- Fixnum :network_id, :null=>false
21
- String :ipv4, :size=>50
22
- Fixnum :alloc_type, :null=>false, :default=>TYPE_AUTO
23
- Text :description
24
-
25
- index [:network_id, :ipv4], {:unique=>true}
26
- index [:instance_nic_id, :network_id]
27
- end
28
- with_timestamps
29
-
30
18
  many_to_one :instance_nic
31
19
  many_to_one :network
32
20
 
@@ -35,7 +23,7 @@ module Dcmgr::Models
35
23
  begin
36
24
  addr = IPAddress::IPv4.new("#{self.ipv4}")
37
25
  # validate if ipv4 is in the range of network_id.
38
- unless network.ipaddress.network.include?(addr)
26
+ unless network.include?(addr)
39
27
  errors.add(:ipv4, "IP address #{addr} is out of range: #{network.canonical_uuid})")
40
28
  end
41
29
  rescue => e
@@ -54,8 +42,8 @@ module Dcmgr::Models
54
42
  # if the IpLease has a pair NAT address it will return
55
43
  # outside IpLease.
56
44
  def nat_outside_lease
57
- if self.network.nat_network_id
58
- self.class.find(:instance_nic_id=>self.instance_nic.id, :network_id=>self.network.nat_network_id)
45
+ if self.instance_nic.nat_network_id
46
+ self.class.find(:instance_nic_id=>self.instance_nic.id, :network_id=>self.instance_nic.nat_network_id)
59
47
  else
60
48
  nil
61
49
  end
@@ -65,7 +53,7 @@ module Dcmgr::Models
65
53
  # @return [IpLease,nil] IpLease (outside) will return inside
66
54
  # IpLease.
67
55
  def nat_inside_lease
68
- if self.network.nat_network_id.nil?
56
+ if self.instance_nic.nat_network_id.nil?
69
57
  self.class.find(:instance_nic_id=>self.instance_nic.id, :network_id=>nil)
70
58
  else
71
59
  nil
@@ -75,14 +63,15 @@ module Dcmgr::Models
75
63
  def self.lease(instance_nic, network)
76
64
  raise TypeError unless instance_nic.is_a?(InstanceNic)
77
65
  raise TypeError unless network.is_a?(Network)
78
-
79
- gwaddr = network.ipaddress
80
- reserved = [gwaddr]
66
+
67
+ reserved = []
68
+ reserved << network.ipv4_gw_ipaddress if network.ipv4_gw
69
+ reserved << IPAddress::IPv4.new(network.dhcp_server) if network.dhcp_server
81
70
  reserved = reserved.map {|i| i.to_u32 }
82
71
  # use SELECT FOR UPDATE to lock rows within same network.
83
- addrs = (gwaddr.network.first.to_u32 .. gwaddr.network.last.to_u32).to_a -
72
+ addrs = network.ipv4_u32_dynamic_range_array -
84
73
  reserved - network.ip_lease_dataset.for_update.all.map {|i| IPAddress::IPv4.new(i.ipv4).to_u32 }
85
- raise "Out of free IP address in this network segment: #{gwaddr.network.to_s}/#{gwaddr.prefix}" if addrs.empty?
74
+ raise "Run out of dynamic IP addresses from the network segment: #{network.ipv4_network.to_s}/#{network.prefix}" if addrs.empty?
86
75
 
87
76
  leaseaddr = IPAddress::IPv4.parse_u32(addrs[rand(addrs.size).to_i])
88
77
  create(:ipv4=>leaseaddr.to_s, :network_id=>network.id, :instance_nic_id=>instance_nic.id)
@@ -4,19 +4,38 @@ module Dcmgr::Models
4
4
  # MAC address lease information
5
5
  class MacLease < BaseNew
6
6
 
7
- inheritable_schema do
8
- String :mac_addr, :size=>12, :fixed=>true, :null=>false
9
-
10
- index :mac_addr, {:unique=>true}
7
+ # register MAC address.
8
+ # @params [String] 6 or 12 length of HEX value in string.
9
+ def self.lease(mac_addr)
10
+ case mac_addr.size
11
+ when 12
12
+ when 6
13
+ # Assign bottom 6 device ID dynamically.
14
+ vendor_id = mac_addr.dup
15
+ begin
16
+ mac_addr = vendor_id + ("%02x%02x%02x" % [rand(0xff),rand(0xff),rand(0xff)])
17
+ end while self.find(:mac_addr=> mac_addr)
18
+ else
19
+ raise ArgumentError, "Invalid MAC address string: 6 or 12 length of HEX value is needed."
20
+ end
21
+ create(:mac_addr=>mac_addr)
11
22
  end
12
- with_timestamps
13
23
 
14
- # dynamically assign new MAC address.
15
- def self.lease(vendor_id='00ff01')
16
- begin
17
- m = vendor_id + ("%02x%02x%02x" % [rand(0xff),rand(0xff),rand(0xff)])
18
- end while self.find(:mac_addr=> m)
19
- create(:mac_addr=>m)
24
+ # show default vendor ID for the hypervisor.
25
+ # The virtual interface can be applied any valid MAC address. But using
26
+ # the well known vendor IDs for hypervisor have some benefits. For
27
+ # example, 70-persistent-net.rules issue can be avoided with newer
28
+ # udev release.
29
+ def self.default_vendor_id(hypervisor)
30
+ case hypervisor.to_sym
31
+ when :kvm
32
+ '525400'
33
+ when :lxc
34
+ # LXC is not known with the specific vendor ID. This may be wrong.
35
+ '525400'
36
+ else
37
+ raise "Unknown hypervisor name: #{hypervisor}"
38
+ end
20
39
  end
21
40
  end
22
41
  end
@@ -7,22 +7,6 @@ module Dcmgr::Models
7
7
  class Network < AccountResource
8
8
  taggable 'nw'
9
9
 
10
- inheritable_schema do
11
- String :ipv4_gw, :null=>false
12
- Fixnum :prefix, :null=>false, :default=>24, :unsigned=>true
13
- String :domain_name
14
- String :dns_server
15
- String :dhcp_server
16
- String :metadata_server
17
- Fixnum :metadata_server_port
18
- Fixnum :bandwidth #in Mbit/s
19
- Fixnum :vlan_lease_id, :null=>false, :default=>0
20
- Fixnum :nat_network_id
21
- Text :description
22
- index :nat_network_id
23
- end
24
- with_timestamps
25
-
26
10
  module IpLeaseMethods
27
11
  def add_reserved(ipaddr, description=nil)
28
12
  model.create(:network_id=>model_object.id,
@@ -37,19 +21,51 @@ module Dcmgr::Models
37
21
  many_to_one :nat_network, :key => :nat_network_id, :class => self
38
22
  one_to_many :inside_networks, :key => :nat_network_id, :class => self
39
23
 
24
+ one_to_many :dhcp_range
25
+ many_to_one :physical_network
26
+
27
+ def before_validation
28
+ self.link_interface ||= "br-#{self[:uuid]}"
29
+ super
30
+ end
31
+
40
32
  def validate
41
33
  super
42
34
 
35
+ unless (1..31).include?(self.prefix.to_i)
36
+ errors.add(:prefix, "prefix must be 1-31: #{self.prefix}")
37
+ end
38
+
39
+ network_addr = begin
40
+ IPAddress::IPv4.new("#{self.ipv4_network}/#{self.prefix}").network
41
+ rescue => e
42
+ errors.add(:ipv4_network, "Invalid IP address syntax: #{self.ipv4_network}")
43
+ end
43
44
  # validate ipv4 syntax
44
- begin
45
- IPAddress::IPv4.new("#{self.ipv4_gw}")
46
- rescue => e
47
- errors.add(:ipv4_gw, "Invalid IP address syntax: #{self.ipv4_gw}")
45
+ if self.ipv4_gw
46
+ begin
47
+ if !network_addr.include?(IPAddress::IPv4.new("#{self.ipv4_gw}"))
48
+ errors.add(:ipv4_gw, "Out of network address range: #{network_addr.to_s}")
49
+ end
50
+ rescue => e
51
+ errors.add(:ipv4_gw, "Invalid IP address syntax: #{self.ipv4_gw}")
52
+ end
53
+ end
54
+
55
+ if self.dhcp_server
56
+ begin
57
+ if !network_addr.include?(IPAddress::IPv4.new("#{self.dhcp_server}"))
58
+ errors.add(:dhcp_server, "Out of network address range: #{network_addr.to_s}")
59
+ end
60
+ rescue => e
61
+ errors.add(:dhcp_server, "Invalid IP address syntax: #{self.dhcp_server}")
62
+ end
48
63
  end
49
64
 
50
- unless (1..31).include?(self.prefix.to_i)
51
- errors.add(:prefix, "prefix must be 1-31: #{self.prefix}")
65
+ if self.link_interface.size > 16
66
+ errors.add(:link_interface, "Can not be the character lenth more than 16(=IF_NAMESIZ) ASCII characters.")
52
67
  end
68
+
53
69
  end
54
70
 
55
71
  def to_hash
@@ -60,6 +76,11 @@ module Dcmgr::Models
60
76
  :description=>description.to_s,
61
77
  :vlan_id => vlan_lease.nil? ? 0 : vlan_lease.tag_id,
62
78
  })
79
+ if self.physical_network
80
+ h[:physical_network] = self.physical_network.to_hash
81
+ end
82
+
83
+ h
63
84
  end
64
85
 
65
86
  def before_destroy
@@ -78,14 +99,19 @@ module Dcmgr::Models
78
99
  end
79
100
 
80
101
  def to_api_document
81
- to_hash
102
+ to_hash.merge(:id=>self.canonical_uuid)
82
103
  end
83
104
 
84
105
  def nat_network
85
106
  Network.find(:id => self.nat_network_id)
86
107
  end
87
108
 
88
- def ipaddress
109
+ def ipv4_ipaddress
110
+ IPAddress::IPv4.new("#{self.ipv4_network}/#{self.prefix}").network
111
+ end
112
+
113
+ def ipv4_gw_ipaddress
114
+ return nil if self.ipv4_gw.nil?
89
115
  IPAddress::IPv4.new("#{self.ipv4_gw}/#{self.prefix}")
90
116
  end
91
117
 
@@ -93,16 +119,111 @@ module Dcmgr::Models
93
119
  # @param [String] ipaddr IP address
94
120
  def include?(ipaddr)
95
121
  ipaddr = ipaddr.is_a?(IPAddress::IPv4) ? ipaddr : IPAddress::IPv4.new(ipaddr)
96
- self.ipaddress.network.include?(ipaddr)
122
+ self.ipv4_ipaddress.network.include?(ipaddr)
97
123
  end
98
124
 
99
125
  # register reserved IP address in this network
100
126
  def add_reserved(ipaddr)
101
- add_ip_lease(:ipv4=>ipaddr, :type=>IpLease::TYPE_RESERVED)
127
+ raise "Out of subnet range: #{ipaddr} to #{self.ipv4_ipaddress}/#{self.prefix}" if !self.include?(ipaddr)
128
+ add_ip_lease(:ipv4=>ipaddr.to_s, :type=>IpLease::TYPE_RESERVED)
102
129
  end
103
130
 
104
131
  def available_ip_nums
105
- self.ipaddress.hosts.size - self.ip_lease_dataset.count
132
+ self.ipv4_ipaddress.hosts.size - self.ip_lease_dataset.count
133
+ end
134
+
135
+ def ipv4_u32_dynamic_range_array
136
+ ary=[]
137
+ dhcp_range_dataset.each { |r|
138
+ ary += (r.range_begin.to_u32 .. r.range_end.to_u32).to_a
139
+ }
140
+ ary
141
+ end
142
+
143
+ def add_ipv4_dynamic_range(range_begin, range_end)
144
+ test_inclusion(*validate_range_args(range_begin, range_end)) { |range, op|
145
+ case op
146
+ when :coverbegin
147
+ range.range_end = range_begin
148
+ when :coverend
149
+ range.range_begin = range_end
150
+ when :inccur
151
+ range.destroy
152
+ end
153
+ range.save_changes
154
+ }
155
+
156
+ self.add_dhcp_range(:range_begin=>range_begin.to_s, :range_end=>range_end.to_s)
157
+
158
+ self
159
+ end
160
+
161
+ def del_ipv4_dynamic_range(range_begin, range_end)
162
+ test_inclusion(*validate_range_args(range_begin, range_end)) { |range, op|
163
+ case op
164
+ when :coverbegin
165
+ range.range_end = range_begin
166
+ when :coverend
167
+ range.range_begin = range_end
168
+ when :inccur
169
+ range.destroy
170
+ when :incnew
171
+ t = range.range_end
172
+ range.range_end = range_begin
173
+ self.add_dhcp_range(:range_begin=>range_end, :range_end=>t)
174
+ end
175
+ range.save_changes
176
+ }
177
+
178
+ self
179
+ end
180
+
181
+ private
182
+ def validate_range_args(range_begin, range_end)
183
+ if range_begin.is_a?(IPAddress::IPv4)
184
+ raise "Different prefix length: range_begin" if range_begin.prefix != self.prefix
185
+ else
186
+ range_begin = IPAddress::IPv4.new("#{range_begin}/#{self.prefix}")
187
+ end
188
+ if range_end.is_a?(IPAddress::IPv4)
189
+ raise "Different prefix length: range_end" if range_end.prefix != self.prefix
190
+ else
191
+ range_end = IPAddress::IPv4.new("#{range_end}/#{self.prefix}")
192
+ end
193
+ if !(self.ipv4_ipaddress.include?(range_begin) && self.ipv4_ipaddress.include?(range_end))
194
+ raise "Given address range is out of the subnet: #{self.ipv4_ipaddress} #{range_begin}-#{range_end}"
195
+ end
196
+ if range_begin > range_end
197
+ t = range_begin
198
+ range_begin = range_end
199
+ range_end = t
200
+ end
201
+ [range_begin, range_end]
202
+ end
203
+
204
+
205
+ def test_inclusion(range_begin, range_end, &blk)
206
+ dhcp_range_dataset.each { |r|
207
+ op = :outrange
208
+ if r.range_begin < range_begin && r.range_end > range_begin
209
+ # range_begin is in the range.
210
+ if r.range_end < range_end
211
+ op = :coverbegin
212
+ else
213
+ # new range is included in current range.
214
+ op = :incnew
215
+ end
216
+ elsif r.range_begin < range_end && r.range_end > range_end
217
+ # range_end is in the range.
218
+ if r.range_begin > range_begin
219
+ op = :coverend
220
+ end
221
+ elsif r.range_begin >= range_begin && r.range_end <= range_end
222
+ # current range is included in new range.
223
+ op = :inccur
224
+ end
225
+ blk.call(r, op)
226
+ }
106
227
  end
107
228
  end
108
229
  end