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.
- data/Rakefile +19 -31
- data/bin/collector +6 -1
- data/config/db/migrations/0001_v1110_origin.rb +446 -0
- data/config/dcmgr.conf.example +51 -0
- data/lib/dcmgr.rb +99 -22
- data/lib/dcmgr/cli/base.rb +34 -1
- data/lib/dcmgr/cli/host.rb +24 -20
- data/lib/dcmgr/cli/image.rb +38 -19
- data/lib/dcmgr/cli/keypair.rb +16 -12
- data/lib/dcmgr/cli/network.rb +189 -81
- data/lib/dcmgr/cli/quota.rb +2 -2
- data/lib/dcmgr/cli/security_group.rb +106 -0
- data/lib/dcmgr/cli/spec.rb +144 -39
- data/lib/dcmgr/cli/storage.rb +16 -15
- data/lib/dcmgr/cli/tag.rb +20 -14
- data/lib/dcmgr/cli/vlan.rb +5 -5
- data/lib/dcmgr/drivers/backing_store.rb +32 -0
- data/lib/dcmgr/drivers/comstar.rb +81 -0
- data/lib/dcmgr/drivers/iijgio_storage.rb +9 -19
- data/lib/dcmgr/drivers/iscsi_target.rb +41 -0
- data/lib/dcmgr/drivers/kvm.rb +161 -28
- data/lib/dcmgr/drivers/linux_iscsi.rb +60 -0
- data/lib/dcmgr/drivers/local_storage.rb +24 -0
- data/lib/dcmgr/drivers/lxc.rb +167 -125
- data/lib/dcmgr/drivers/raw.rb +74 -0
- data/lib/dcmgr/drivers/s3_storage.rb +7 -19
- data/lib/dcmgr/drivers/snapshot_storage.rb +18 -28
- data/lib/dcmgr/drivers/storage_initiator.rb +28 -0
- data/lib/dcmgr/drivers/sun_iscsi.rb +32 -0
- data/lib/dcmgr/drivers/zfs.rb +77 -0
- data/lib/dcmgr/endpoints/core_api.rb +315 -263
- data/lib/dcmgr/endpoints/errors.rb +21 -10
- data/lib/dcmgr/endpoints/metadata.rb +360 -23
- data/lib/dcmgr/helpers/cli_helper.rb +6 -3
- data/lib/dcmgr/helpers/ec2_metadata_helper.rb +9 -0
- data/lib/dcmgr/helpers/nic_helper.rb +11 -0
- data/lib/dcmgr/helpers/snapshot_storage_helper.rb +34 -0
- data/lib/dcmgr/models/account.rb +0 -6
- data/lib/dcmgr/models/account_resource.rb +0 -4
- data/lib/dcmgr/models/base_new.rb +14 -2
- data/lib/dcmgr/models/dhcp_range.rb +38 -0
- data/lib/dcmgr/models/frontend_system.rb +0 -6
- data/lib/dcmgr/models/history.rb +0 -11
- data/lib/dcmgr/models/host_node.rb +131 -0
- data/lib/dcmgr/models/hostname_lease.rb +0 -8
- data/lib/dcmgr/models/image.rb +31 -18
- data/lib/dcmgr/models/instance.rb +137 -143
- data/lib/dcmgr/models/instance_nic.rb +52 -29
- data/lib/dcmgr/models/instance_security_group.rb +9 -0
- data/lib/dcmgr/models/instance_spec.rb +163 -31
- data/lib/dcmgr/models/ip_lease.rb +10 -21
- data/lib/dcmgr/models/mac_lease.rb +30 -11
- data/lib/dcmgr/models/network.rb +148 -27
- data/lib/dcmgr/models/physical_network.rb +18 -0
- data/lib/dcmgr/models/quota.rb +0 -10
- data/lib/dcmgr/models/request_log.rb +3 -18
- data/lib/dcmgr/models/security_group.rb +66 -0
- data/lib/dcmgr/models/security_group_rule.rb +145 -0
- data/lib/dcmgr/models/ssh_key_pair.rb +16 -19
- data/lib/dcmgr/models/{storage_pool.rb → storage_node.rb} +35 -25
- data/lib/dcmgr/models/tag.rb +0 -14
- data/lib/dcmgr/models/tag_mapping.rb +1 -7
- data/lib/dcmgr/models/vlan_lease.rb +2 -8
- data/lib/dcmgr/models/volume.rb +49 -37
- data/lib/dcmgr/models/volume_snapshot.rb +15 -17
- data/lib/dcmgr/node_modules/hva_collector.rb +69 -28
- data/lib/dcmgr/node_modules/instance_ha.rb +23 -12
- data/lib/dcmgr/node_modules/instance_monitor.rb +16 -2
- data/lib/dcmgr/node_modules/openflow_controller.rb +784 -0
- data/lib/dcmgr/node_modules/scheduler.rb +189 -0
- data/lib/dcmgr/node_modules/service_netfilter.rb +452 -227
- data/lib/dcmgr/node_modules/service_openflow.rb +731 -0
- data/lib/dcmgr/node_modules/sta_collector.rb +20 -0
- data/lib/dcmgr/node_modules/sta_tgt_initializer.rb +35 -0
- data/lib/dcmgr/rack/request_logger.rb +11 -6
- data/lib/dcmgr/rpc/hva_handler.rb +256 -110
- data/lib/dcmgr/rpc/sta_handler.rb +244 -0
- data/lib/dcmgr/scheduler.rb +122 -8
- data/lib/dcmgr/scheduler/host_node/exclude_same.rb +24 -0
- data/lib/dcmgr/scheduler/host_node/find_first.rb +12 -0
- data/lib/dcmgr/scheduler/host_node/least_usage.rb +28 -0
- data/lib/dcmgr/scheduler/host_node/per_instance.rb +18 -0
- data/lib/dcmgr/scheduler/host_node/specify_node.rb +26 -0
- data/lib/dcmgr/scheduler/network/flat_single.rb +23 -0
- data/lib/dcmgr/scheduler/network/nat_one_to_one.rb +23 -0
- data/lib/dcmgr/scheduler/network/per_instance.rb +39 -0
- data/lib/dcmgr/scheduler/network/vif_template.rb +19 -0
- data/lib/dcmgr/scheduler/storage_node/find_first.rb +13 -0
- data/lib/dcmgr/scheduler/storage_node/least_usage.rb +23 -0
- data/lib/dcmgr/storage_service.rb +39 -40
- data/lib/dcmgr/tags.rb +3 -3
- data/lib/dcmgr/version.rb +1 -1
- data/lib/dcmgr/vnet.rb +105 -0
- data/lib/dcmgr/vnet/factories.rb +141 -0
- data/lib/dcmgr/vnet/isolators/by_securitygroup.rb +21 -0
- data/lib/dcmgr/vnet/isolators/dummy.rb +17 -0
- data/lib/dcmgr/vnet/netfilter/cache.rb +51 -0
- data/lib/dcmgr/vnet/netfilter/chain.rb +66 -0
- data/lib/dcmgr/vnet/netfilter/controller.rb +193 -0
- data/lib/dcmgr/vnet/netfilter/ebtables_rule.rb +53 -0
- data/lib/dcmgr/vnet/netfilter/iptables_rule.rb +45 -0
- data/lib/dcmgr/vnet/netfilter/task_manager.rb +459 -0
- data/lib/dcmgr/vnet/tasks/accept_all_dns.rb +19 -0
- data/lib/dcmgr/vnet/tasks/accept_arp_broadcast.rb +24 -0
- data/lib/dcmgr/vnet/tasks/accept_arp_from_friends.rb +34 -0
- data/lib/dcmgr/vnet/tasks/accept_arp_from_gateway.rb +21 -0
- data/lib/dcmgr/vnet/tasks/accept_arp_to_host.rb +30 -0
- data/lib/dcmgr/vnet/tasks/accept_ip_from_friends.rb +26 -0
- data/lib/dcmgr/vnet/tasks/accept_ip_from_gateway.rb +23 -0
- data/lib/dcmgr/vnet/tasks/accept_ip_to_anywhere.rb +18 -0
- data/lib/dcmgr/vnet/tasks/accept_related_established.rb +45 -0
- data/lib/dcmgr/vnet/tasks/accept_wakame_dhcp_only.rb +33 -0
- data/lib/dcmgr/vnet/tasks/accept_wakame_dns_only.rb +33 -0
- data/lib/dcmgr/vnet/tasks/debug_iptables.rb +21 -0
- data/lib/dcmgr/vnet/tasks/drop_arp_forwarding.rb +27 -0
- data/lib/dcmgr/vnet/tasks/drop_arp_to_host.rb +24 -0
- data/lib/dcmgr/vnet/tasks/drop_ip_from_anywhere.rb +18 -0
- data/lib/dcmgr/vnet/tasks/drop_ip_spoofing.rb +34 -0
- data/lib/dcmgr/vnet/tasks/drop_mac_spoofing.rb +33 -0
- data/lib/dcmgr/vnet/tasks/exclude_from_nat.rb +47 -0
- data/lib/dcmgr/vnet/tasks/security_group.rb +37 -0
- data/lib/dcmgr/vnet/tasks/static_nat.rb +54 -0
- data/lib/dcmgr/vnet/tasks/translate_metadata_address.rb +32 -0
- data/web/metadata/config.ru +1 -1
- metadata +174 -89
- data/lib/dcmgr/cli/group.rb +0 -101
- data/lib/dcmgr/endpoints/core_api_mock.rb +0 -865
- data/lib/dcmgr/models/host_pool.rb +0 -122
- data/lib/dcmgr/models/instance_netfilter_group.rb +0 -16
- data/lib/dcmgr/models/netfilter_group.rb +0 -89
- data/lib/dcmgr/models/netfilter_rule.rb +0 -21
- data/lib/dcmgr/scheduler/find_last.rb +0 -16
- data/lib/dcmgr/scheduler/find_random.rb +0 -16
- data/lib/dcmgr/stm/instance.rb +0 -25
- data/lib/dcmgr/stm/snapshot_context.rb +0 -33
- data/lib/dcmgr/stm/volume_context.rb +0 -65
@@ -0,0 +1,244 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'isono'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Dcmgr
|
6
|
+
module Rpc
|
7
|
+
|
8
|
+
class StaHandler < EndpointBuilder
|
9
|
+
include Dcmgr::Logger
|
10
|
+
include Dcmgr::Helpers::CliHelper
|
11
|
+
|
12
|
+
def select_backing_store
|
13
|
+
backing_store = @node.manifest.config.backing_store
|
14
|
+
@backing_store = Dcmgr::Drivers::BackingStore.select_backing_store(backing_store)
|
15
|
+
end
|
16
|
+
|
17
|
+
def select_iscsi_target
|
18
|
+
iscsi_target = @node.manifest.config.iscsi_target
|
19
|
+
@iscsi_target = Dcmgr::Drivers::IscsiTarget.select_iscsi_target(iscsi_target, @node)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Setup volume file from snapshot storage and register to
|
23
|
+
# sotrage target.
|
24
|
+
def setup_and_export_volume
|
25
|
+
snapshot_file = nil
|
26
|
+
unless @volume[:snapshot_id].nil?
|
27
|
+
@snapshot = rpc.request('sta-collector', 'get_snapshot', @volume[:snapshot_id])
|
28
|
+
raise "Invalid snapshot state: #{@snapshot[:state]}" unless @snapshot[:state].to_s == 'available'
|
29
|
+
snap_filename = @destination[:filename]
|
30
|
+
|
31
|
+
begin
|
32
|
+
storage_service = Dcmgr::StorageService.new(@destination[:driver], {
|
33
|
+
:account_id => @snapshot[:account_id],
|
34
|
+
:access_key => @destination[:access_key],
|
35
|
+
:secret_key => @destination[:secret_key],
|
36
|
+
})
|
37
|
+
snapshot_storage = storage_service.snapshot_storage(@destination[:bucket], @destination[:path])
|
38
|
+
snapshot_storage.download(snap_filename)
|
39
|
+
snapshot_file = snapshot_storage.snapshot(snap_filename)
|
40
|
+
logger.info("download to #{@destination[:driver]}: #{snap_filename}")
|
41
|
+
rescue => e
|
42
|
+
logger.error(e)
|
43
|
+
raise "snapshot not downloaded"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
logger.info("creating new volume #{@volume_id}")
|
48
|
+
|
49
|
+
rpc.request('sta-collector', 'update_volume', @volume_id, {:state=>:creating, :export_path=>@volume[:uuid]})
|
50
|
+
|
51
|
+
select_backing_store
|
52
|
+
@backing_store.create_volume(StaContext.new(self), snapshot_file)
|
53
|
+
|
54
|
+
unless @volume[:snapshot_id].nil?
|
55
|
+
snapshot_storage.clear
|
56
|
+
end
|
57
|
+
|
58
|
+
select_iscsi_target
|
59
|
+
opt = @iscsi_target.create(StaContext.new(self))
|
60
|
+
rpc.request('sta-collector', 'update_volume', @volume_id, {:state=>:available, :transport_information=>opt})
|
61
|
+
logger.info("registered iscsi target: #{@volume_id}")
|
62
|
+
end
|
63
|
+
|
64
|
+
job :create_volume, proc {
|
65
|
+
@volume_id = request.args[0]
|
66
|
+
@destination = Dcmgr::StorageService.repository(request.args[1])
|
67
|
+
@volume = rpc.request('sta-collector', 'get_volume', @volume_id)
|
68
|
+
raise "Invalid volume state: #{@volume[:state]}" unless @volume[:state].to_s == 'pending'
|
69
|
+
|
70
|
+
setup_and_export_volume
|
71
|
+
}, proc {
|
72
|
+
# TODO: need to clear generated temp files or remote files in remote snapshot repository.
|
73
|
+
rpc.request('sta-collector', 'update_volume', @volume_id, {:state=>:deleted, :deleted_at=>Time.now.utc})
|
74
|
+
logger.error("Failed to run create_volume: #{@volume_id}")
|
75
|
+
}
|
76
|
+
|
77
|
+
# create volume and chain to run instance.
|
78
|
+
job :create_volume_and_run_instance, proc {
|
79
|
+
@volume_id = request.args[0]
|
80
|
+
@instance_id = request.args[1]
|
81
|
+
@destination = Dcmgr::StorageService.repository(request.args[2])
|
82
|
+
|
83
|
+
@volume = rpc.request('sta-collector', 'get_volume', @volume_id)
|
84
|
+
raise "Invalid volume state: #{@volume[:state]}" unless @volume[:state].to_s == 'pending'
|
85
|
+
|
86
|
+
setup_and_export_volume
|
87
|
+
|
88
|
+
@instance = rpc.request('hva-collector', 'get_instance', @instance_id)
|
89
|
+
jobreq.submit("hva-handle.#{@instance[:host_node][:node_id]}", 'run_vol_store', @instance_id, @volume_id)
|
90
|
+
}, proc {
|
91
|
+
# TODO: need to clear generated temp files or remote files in remote snapshot repository.
|
92
|
+
rpc.request('sta-collector', 'update_volume', @volume_id, {:state=>:deleted, :deleted_at=>Time.now.utc})
|
93
|
+
rpc.request('hva-collector', 'update_instance', @instance_id, {:state=>:terminated, :terminated_at=>Time.now.utc})
|
94
|
+
logger.error("Failed to run create_volume_and_run_instance: #{@instance_id}, #{@volume_id}")
|
95
|
+
}
|
96
|
+
|
97
|
+
job :delete_volume do
|
98
|
+
@volume_id = request.args[0]
|
99
|
+
@volume = rpc.request('sta-collector', 'get_volume', @volume_id)
|
100
|
+
logger.info("#{@volume_id}: start deleting volume.")
|
101
|
+
errcount = 0
|
102
|
+
if @volume[:state].to_s == 'deleted'
|
103
|
+
raise "#{@volume_id}: Invalid volume state: deleted"
|
104
|
+
end
|
105
|
+
if @volume[:state].to_s != 'deregistering'
|
106
|
+
logger.warn("#{@volume_id}: Unexpected volume state but try destroy resource: #{@volume[:state]}")
|
107
|
+
end
|
108
|
+
|
109
|
+
# deregisterd iscsi target
|
110
|
+
select_iscsi_target
|
111
|
+
begin
|
112
|
+
@iscsi_target.delete(StaContext.new(self))
|
113
|
+
rescue => e
|
114
|
+
logger.error("#{@volume_id}: Failed to delete ISCSI target entry.")
|
115
|
+
errcount += 1
|
116
|
+
end
|
117
|
+
|
118
|
+
rpc.request('sta-collector', 'update_volume', @volume_id, {:state=>:deleting})
|
119
|
+
|
120
|
+
# delete volume
|
121
|
+
select_backing_store
|
122
|
+
begin
|
123
|
+
@backing_store.delete_volume(StaContext.new(self))
|
124
|
+
rescue => e
|
125
|
+
logger.error("#{@volume_id}: Failed to delete zfs volume: #{@volume[:storage_node][:export_path]}/#{@volume[:uuid]}")
|
126
|
+
errcount += 1
|
127
|
+
end
|
128
|
+
|
129
|
+
rpc.request('sta-collector', 'update_volume', @volume_id, {:state=>:deleted, :deleted_at=>Time.now.utc})
|
130
|
+
if errcount > 0
|
131
|
+
logger.info("#{@volume_id}: Encountered one or more errors during deleting.")
|
132
|
+
else
|
133
|
+
logger.info("#{@volume_id}: Deleted volume successfully.")
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
job :create_snapshot, proc {
|
138
|
+
@snapshot_id = request.args[0]
|
139
|
+
@destination = Dcmgr::StorageService.repository(request.args[1])
|
140
|
+
@snapshot = rpc.request('sta-collector', 'get_snapshot', @snapshot_id) unless @snapshot_id.nil?
|
141
|
+
@volume = rpc.request('sta-collector', 'get_volume', @snapshot[:origin_volume_id])
|
142
|
+
|
143
|
+
logger.info("create new snapshot: #{@snapshot_id}")
|
144
|
+
raise "Invalid volume state: #{@volume[:state]}" unless %w(available attached).member?(@volume[:state].to_s)
|
145
|
+
|
146
|
+
begin
|
147
|
+
storage_service = Dcmgr::StorageService.new(@destination[:driver], {
|
148
|
+
:account_id => @snapshot[:account_id],
|
149
|
+
:access_key => @destination[:access_key],
|
150
|
+
:secret_key => @destination[:secret_key],
|
151
|
+
})
|
152
|
+
snapshot_storage = storage_service.snapshot_storage(@destination[:bucket], @destination[:path])
|
153
|
+
select_backing_store
|
154
|
+
|
155
|
+
snap_filename = @destination[:filename]
|
156
|
+
@backing_store.create_snapshot(StaContext.new(self), snapshot_storage.snapshot(snap_filename))
|
157
|
+
|
158
|
+
snapshot_storage.upload(snap_filename)
|
159
|
+
snapshot_storage.clear
|
160
|
+
logger.info("upload to #{@destination[:driver]}: #{snap_filename}")
|
161
|
+
rescue => e
|
162
|
+
logger.error(e)
|
163
|
+
raise "snapshot has not be uploaded"
|
164
|
+
end
|
165
|
+
|
166
|
+
rpc.request('sta-collector', 'update_snapshot', @snapshot_id, {:state=>:available})
|
167
|
+
logger.info("created new snapshot: #{@snapshot_id}")
|
168
|
+
}, proc {
|
169
|
+
# TODO: need to clear generated temp files or remote files in remote snapshot repository.
|
170
|
+
rpc.request('sta-collector', 'update_snapshot', @snapshot_id, {:state=>:deleted, :deleted_at=>Time.now.utc})
|
171
|
+
logger.error("Failed to run create_snapshot: #{@snapshot_id}")
|
172
|
+
}
|
173
|
+
|
174
|
+
job :delete_snapshot do
|
175
|
+
@snapshot_id = request.args[0]
|
176
|
+
@destination = Dcmgr::StorageService.repository(request.args[1])
|
177
|
+
@snapshot = rpc.request('sta-collector', 'get_snapshot', @snapshot_id)
|
178
|
+
@volume = rpc.request('sta-collector', 'get_volume', @snapshot[:origin_volume_id])
|
179
|
+
logger.info("deleting snapshot: #{@snapshot_id}")
|
180
|
+
raise "Invalid snapshot state: #{@snapshot[:state]}" unless @snapshot[:state].to_s == 'deleting'
|
181
|
+
begin
|
182
|
+
storage_service = Dcmgr::StorageService.new(@destination[:driver], {
|
183
|
+
:account_id => @snapshot[:account_id],
|
184
|
+
:access_key => @destination[:access_key],
|
185
|
+
:secret_key => @destination[:secret_key],
|
186
|
+
})
|
187
|
+
snapshot_storage = storage_service.snapshot_storage(@destination[:bucket], @destination[:path])
|
188
|
+
snapshot_storage.delete(@destination[:filename])
|
189
|
+
rescue => e
|
190
|
+
logger.error(e)
|
191
|
+
raise "snapshot has not be deleted"
|
192
|
+
end
|
193
|
+
|
194
|
+
rpc.request('sta-collector', 'update_snapshot', @snapshot_id, {:state=>:deleted, :deleted_at=>Time.now.utc})
|
195
|
+
logger.info("deleted snapshot: #{@snapshot_id}")
|
196
|
+
end
|
197
|
+
|
198
|
+
def rpc
|
199
|
+
@rpc ||= Isono::NodeModules::RpcChannel.new(@node)
|
200
|
+
end
|
201
|
+
|
202
|
+
def jobreq
|
203
|
+
@jobreq ||= Isono::NodeModules::JobChannel.new(@node)
|
204
|
+
end
|
205
|
+
|
206
|
+
def event
|
207
|
+
@event ||= Isono::NodeModules::EventChannel.new(@node)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
class StaContext
|
212
|
+
|
213
|
+
def initialize(stahandler)
|
214
|
+
raise "Invalid Class: #{stahandler}" unless stahandler.instance_of?(StaHandler)
|
215
|
+
@sta = stahandler
|
216
|
+
end
|
217
|
+
|
218
|
+
def volume_id
|
219
|
+
@sta.instance_variable_get(:@volume_id)
|
220
|
+
end
|
221
|
+
|
222
|
+
def snapshot_id
|
223
|
+
@sta.instance_variable_get(:@snapshot_id)
|
224
|
+
end
|
225
|
+
|
226
|
+
def destination
|
227
|
+
@sta.instance_variable_get(:@destination)
|
228
|
+
end
|
229
|
+
|
230
|
+
def volume
|
231
|
+
@sta.instance_variable_get(:@volume)
|
232
|
+
end
|
233
|
+
|
234
|
+
def snapshot
|
235
|
+
@sta.instance_variable_get(:@snapshot)
|
236
|
+
end
|
237
|
+
|
238
|
+
def node
|
239
|
+
@sta.instance_variable_get(:@node)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
244
|
+
end
|
data/lib/dcmgr/scheduler.rb
CHANGED
@@ -1,12 +1,126 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'extlib/module'
|
4
|
+
require 'configuration'
|
1
5
|
|
2
6
|
module Dcmgr
|
3
|
-
module
|
4
|
-
class
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
module Scheduler
|
8
|
+
class SchedulerError < StandardError; end
|
9
|
+
class HostNodeSchedulingError < SchedulerError; end
|
10
|
+
class StorageNodeSchedulingError < SchedulerError; end
|
11
|
+
class NetworkSchedulingError < SchedulerError; end
|
12
|
+
|
13
|
+
# Factory method for HostNode scheduler
|
14
|
+
def self.host_node()
|
15
|
+
c = scheduler_class(Dcmgr.conf.host_node_scheduler, ::Dcmgr::Scheduler::HostNode)
|
16
|
+
if Dcmgr.conf.host_node_scheduler.respond_to?(:options)
|
17
|
+
c.new(Dcmgr.conf.host_node_scheduler.options)
|
18
|
+
else
|
19
|
+
c.new
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Factory method for HostNode scheduler for HA
|
24
|
+
def self.host_node_ha()
|
25
|
+
c = scheduler_class(Dcmgr.conf.host_node_ha_scheduler, ::Dcmgr::Scheduler::HostNode)
|
26
|
+
if Dcmgr.conf.host_node_ha_scheduler.respond_to?(:options)
|
27
|
+
c.new(Dcmgr.conf.host_node_ha_scheduler.options)
|
28
|
+
else
|
29
|
+
c.new
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Factory method for StorageNode scheduler
|
34
|
+
def self.storage_node()
|
35
|
+
c = scheduler_class(Dcmgr.conf.storage_node_scheduler, ::Dcmgr::Scheduler::StorageNode)
|
36
|
+
if Dcmgr.conf.storage_node_scheduler.respond_to?(:options)
|
37
|
+
c.new(Dcmgr.conf.storage_node_scheduler.options)
|
38
|
+
else
|
39
|
+
c.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Factory method for Network scheduler
|
44
|
+
def self.network()
|
45
|
+
c = scheduler_class(Dcmgr.conf.network_scheduler, ::Dcmgr::Scheduler::Network)
|
46
|
+
if Dcmgr.conf.network_scheduler.respond_to?(:options)
|
47
|
+
c.new(Dcmgr.conf.network_scheduler.options)
|
48
|
+
else
|
49
|
+
c.new
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# common scheduler class finder
|
54
|
+
def self.scheduler_class(input, namespace)
|
55
|
+
c = case input
|
56
|
+
when Symbol
|
57
|
+
namespace.const_get(input)
|
58
|
+
when ::Configuration
|
59
|
+
if input.respond_to?(:scheduler)
|
60
|
+
namespace.const_get(input.scheduler)
|
61
|
+
else
|
62
|
+
raise "Missing configuration key: scheduler"
|
63
|
+
end
|
64
|
+
else
|
65
|
+
raise "Unknown #{namespace.to_s} scheduler: #{input}"
|
66
|
+
end
|
67
|
+
raise TypeError unless c < Module.find_const("#{namespace.to_s}Scheduler")
|
68
|
+
c
|
69
|
+
end
|
70
|
+
|
71
|
+
# Allocate HostNode to Instance object.
|
72
|
+
class HostNodeScheduler
|
73
|
+
def initialize(options=nil)
|
74
|
+
@options = options
|
75
|
+
end
|
76
|
+
|
77
|
+
# @param Models::Instance instance
|
78
|
+
# @return Models::HostNode
|
79
|
+
def schedule(instance)
|
80
|
+
raise NotImplementedError
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Allocate StorageNode to Volume object.
|
85
|
+
class StorageNodeScheduler
|
86
|
+
def initialize(options=nil)
|
87
|
+
@options = options
|
88
|
+
end
|
89
|
+
|
90
|
+
# @param Models::Volume volume
|
91
|
+
# @return nil
|
92
|
+
def schedule(volume)
|
93
|
+
if volume.snapshot_id
|
94
|
+
# use same same storage node if it is local snapshot.
|
95
|
+
if volume.snapshot.destination == 'local'
|
96
|
+
volume.storage_node = Models::StorageNode[volume.snapshot.storage_node_id]
|
97
|
+
else
|
98
|
+
schedule_node(volume)
|
99
|
+
end
|
100
|
+
else
|
101
|
+
schedule_node(volume)
|
102
|
+
end
|
103
|
+
raise StorageNodeSchedulingError if volume.storage_node.nil?
|
104
|
+
end
|
105
|
+
|
106
|
+
protected
|
107
|
+
def schedule_node(volume)
|
108
|
+
raise NotImplementedError
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Manage vnic for instances and assign network object.
|
113
|
+
class NetworkScheduler
|
114
|
+
def initialize(options=nil)
|
115
|
+
@options = options
|
116
|
+
end
|
117
|
+
|
118
|
+
# @param Models::HostNode host_node
|
119
|
+
# @return Models::Network
|
120
|
+
def schedule(instance)
|
121
|
+
raise NotImplementedError
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
11
125
|
end
|
12
126
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Dcmgr
|
4
|
+
module Scheduler
|
5
|
+
module HostNode
|
6
|
+
|
7
|
+
class ExcludeSame < HostNodeScheduler
|
8
|
+
include Dcmgr::Logger
|
9
|
+
|
10
|
+
def schedule(instance)
|
11
|
+
ds = Models::HostNode.online_nodes.filter(:arch=>instance.spec.arch,
|
12
|
+
:hypervisor=>instance.spec.hypervisor)
|
13
|
+
|
14
|
+
host_node = ds.all.find_all { |hn|
|
15
|
+
hn.node_id != instance.host_node.node_id
|
16
|
+
}.first
|
17
|
+
|
18
|
+
raise HostNodeSchedulingError if host_node.nil?
|
19
|
+
instance.host_node = host_node
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Dcmgr; module Scheduler; module HostNode
|
4
|
+
class FindFirst < HostNodeScheduler
|
5
|
+
|
6
|
+
def schedule(instance)
|
7
|
+
host_node = Models::HostNode.first
|
8
|
+
raise HostNodeScheduleError if host_node.nil?
|
9
|
+
instance.host_node = host_node
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end; end; end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Dcmgr
|
4
|
+
module Scheduler
|
5
|
+
module HostNode
|
6
|
+
|
7
|
+
# Find host node which has the largest available capacity.
|
8
|
+
class LeastUsage < HostNodeScheduler
|
9
|
+
include Dcmgr::Logger
|
10
|
+
|
11
|
+
def schedule(instance)
|
12
|
+
ds = Models::HostNode.online_nodes.filter(:arch=>instance.spec.arch,
|
13
|
+
:hypervisor=>instance.spec.hypervisor)
|
14
|
+
|
15
|
+
host_node = ds.all.find_all { |hn|
|
16
|
+
hn.available_cpu_cores >= instance.cpu_cores && \
|
17
|
+
hn.available_memory_size >= instance.memory_size
|
18
|
+
}.sort_by { |hn|
|
19
|
+
hn.available_memory_size
|
20
|
+
}.reverse.first
|
21
|
+
|
22
|
+
raise HostNodeSchedulingError if host_node.nil?
|
23
|
+
instance.host_node = host_node
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Dcmgr
|
4
|
+
module Scheduler
|
5
|
+
module HostNode
|
6
|
+
# Meta scheduler calls another scheduler specified by API.
|
7
|
+
class PerInstance < HostNodeScheduler
|
8
|
+
|
9
|
+
def schedule(instance)
|
10
|
+
sched_name = instance.request_params[:host_node_scheduler]
|
11
|
+
|
12
|
+
sched = Scheduler.scheduler_class(sched_name, ::Dcmgr::Scheduler::HostNode)
|
13
|
+
sched.schedule(instance)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|