foreman_fog_proxmox 0.24.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/concerns/foreman_fog_proxmox/controller/parameters/compute_resource.rb +1 -2
- data/app/controllers/foreman_fog_proxmox/compute_resources_controller.rb +1 -2
- data/app/models/foreman_fog_proxmox/proxmox.rb +0 -10
- data/app/models/foreman_fog_proxmox/proxmox_images.rb +20 -33
- data/app/models/foreman_fog_proxmox/proxmox_pools.rb +2 -19
- data/app/models/foreman_fog_proxmox/proxmox_vm_commands.rb +9 -4
- data/app/models/foreman_fog_proxmox/proxmox_vm_new.rb +12 -1
- data/app/models/foreman_fog_proxmox/proxmox_vm_queries.rb +13 -36
- data/app/views/api/v2/compute_resources/proxmox.json.rabl +1 -1
- data/app/views/compute_resources/form/_proxmox.html.erb +0 -2
- data/app/views/compute_resources/show/_proxmox.html.erb +4 -4
- data/lib/foreman_fog_proxmox/engine.rb +13 -10
- data/lib/foreman_fog_proxmox/version.rb +1 -1
- data/test/functional/compute_resources_controller_test.rb +0 -12
- data/test/unit/foreman_fog_proxmox/proxmox_test.rb +0 -27
- data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_server_create_test.rb +10 -7
- data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_server_update_test.rb +4 -4
- data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_test.rb +25 -0
- data/test/unit/foreman_fog_proxmox/proxmox_vm_new_test.rb +46 -0
- data/test/unit/foreman_fog_proxmox/proxmox_vm_queries_test.rb +2 -61
- data/webpack/components/ProxmoxStoragesUtils.js +6 -2
- data/webpack/global_test_setup.js +2 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 329a340fdfd2b5e117a05a227477e29108df61d303a5ce5a5a2dc148ae41ec7c
|
|
4
|
+
data.tar.gz: '08b9aa3dca59fb2b7a80c2f1e6b0b59c9931f0d974e8d9849a720d6d37a819be'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '094a19a8592b2ed3ad7a88c637c7859f3bbc631a4f08f2fb781ec21a8b9620789fb701dbab917973ee122fb2ead5a44d6af12a28fe6dd2d99dad2267c8d051a7'
|
|
7
|
+
data.tar.gz: ce956eaac9a5faf92f2decd8721910dd72fd9a0e7f0ccfbeab40462c1cfc7892897235e7d2fef925405abf993b85f902edac0f4afcb1ec685649d27df0e61168
|
|
@@ -27,8 +27,7 @@ module ForemanFogProxmox
|
|
|
27
27
|
def compute_resource_params_filter
|
|
28
28
|
super.tap do |filter|
|
|
29
29
|
filter.permit :ssl_verify_peer,
|
|
30
|
-
:ssl_certs, :disable_proxy, :auth_method, :token_id, :token
|
|
31
|
-
:caching_enabled
|
|
30
|
+
:ssl_certs, :disable_proxy, :auth_method, :token_id, :token
|
|
32
31
|
end
|
|
33
32
|
end
|
|
34
33
|
|
|
@@ -84,8 +84,7 @@ module ForemanFogProxmox
|
|
|
84
84
|
node_id = params[:node_id]
|
|
85
85
|
storage = params[:storage]
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
vols = node&.storages&.get(storage)&.volumes || []
|
|
87
|
+
vols = cr.storages(node_id).find { |s| s.storage == storage }&.volumes || []
|
|
89
88
|
|
|
90
89
|
render json: Array(vols).map { |v|
|
|
91
90
|
h = v.respond_to?(:as_json) ? v.as_json : v
|
|
@@ -36,8 +36,6 @@ module ForemanFogProxmox
|
|
|
36
36
|
include ProxmoxVersion
|
|
37
37
|
include ProxmoxConsole
|
|
38
38
|
include ComputeAttributesUpdateDetector
|
|
39
|
-
include ComputeResourceCaching
|
|
40
|
-
|
|
41
39
|
validates :url, :format => { :with => URI::DEFAULT_PARSER.make_regexp }, :presence => true
|
|
42
40
|
validates :auth_method, :presence => true, :inclusion => { in: ['access_ticket', 'user_token'],
|
|
43
41
|
message: ->(value) do format('%<value>s is not a valid authentication method', { value: value }) end }
|
|
@@ -131,14 +129,6 @@ module ForemanFogProxmox
|
|
|
131
129
|
|
|
132
130
|
private
|
|
133
131
|
|
|
134
|
-
def structs_from_cache(items)
|
|
135
|
-
Array(items).map { |item| OpenStruct.new(item) }
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def extract_attributes(resource, fields)
|
|
139
|
-
slice_vm_attributes(fields.index_with { |field| resource.try(field) }, fields)
|
|
140
|
-
end
|
|
141
|
-
|
|
142
132
|
def fog_credentials
|
|
143
133
|
hash = {
|
|
144
134
|
proxmox_url: url,
|
|
@@ -24,18 +24,11 @@ module ForemanFogProxmox
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def images_by_storage(node_id, storage_id, type = 'iso')
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
storage.volumes.list_by_content_type(type).sort_by(&:volid).map do |volume|
|
|
34
|
-
extract_attributes(volume, [:volid, :content, :format, :size, :used])
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
structs_from_cache(cached_images)
|
|
27
|
+
node = client.nodes.get node_id
|
|
28
|
+
node ||= default_node
|
|
29
|
+
storage = node.storages.get storage_id if storage_id
|
|
30
|
+
logger.debug("images_by_storage(): node_id #{node_id} storage_id #{storage_id} type #{type}")
|
|
31
|
+
storage.volumes.list_by_content_type(type).sort_by(&:volid) if storage
|
|
39
32
|
end
|
|
40
33
|
|
|
41
34
|
def template_name(template)
|
|
@@ -52,31 +45,25 @@ module ForemanFogProxmox
|
|
|
52
45
|
end
|
|
53
46
|
|
|
54
47
|
def templates
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
logger.warn("Skipping disabled storage #{storage.identity} on #{node.node}")
|
|
63
|
-
next []
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# Fetch QEMU and LXC template images
|
|
67
|
-
storage.volumes.list_by_content_type('images') + storage.volumes.list_by_content_type('rootdir')
|
|
68
|
-
rescue StandardError => e
|
|
69
|
-
logger.error("Failed to fetch volumes for storage #{storage.identity} on #{node.node}: #{e.message}")
|
|
70
|
-
[]
|
|
48
|
+
volumes = []
|
|
49
|
+
nodes.each do |node|
|
|
50
|
+
storages(node.node).each do |storage|
|
|
51
|
+
# Skip disabled storages (enabled == 0 or nil)
|
|
52
|
+
unless storage.enabled.to_i == 1
|
|
53
|
+
logger.warn("Skipping disabled storage #{storage.identity} on #{node.node}")
|
|
54
|
+
next
|
|
71
55
|
end
|
|
72
|
-
end
|
|
73
56
|
|
|
74
|
-
|
|
75
|
-
|
|
57
|
+
# Fetch QEMU and LXC template images
|
|
58
|
+
volumes += storage.volumes.list_by_content_type('images')
|
|
59
|
+
volumes += storage.volumes.list_by_content_type('rootdir')
|
|
60
|
+
rescue StandardError => e
|
|
61
|
+
logger.error("Failed to fetch volumes for storage #{storage.identity} on #{node.node}: #{e.message}")
|
|
62
|
+
next
|
|
76
63
|
end
|
|
77
64
|
end
|
|
78
|
-
|
|
79
|
-
|
|
65
|
+
# for creating image, only list volumes which are templated
|
|
66
|
+
volumes.select(&:template?)
|
|
80
67
|
end
|
|
81
68
|
|
|
82
69
|
def template(uuid)
|
|
@@ -20,25 +20,8 @@
|
|
|
20
20
|
module ForemanFogProxmox
|
|
21
21
|
module ProxmoxPools
|
|
22
22
|
def pools
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
pools.sort_by(&:poolid).map do |pool|
|
|
26
|
-
extract_attributes(pool, [:poolid, :comment]).merge(
|
|
27
|
-
members: Array(pool.try(:members)).map do |member|
|
|
28
|
-
{ vmid: member['vmid'] }
|
|
29
|
-
end
|
|
30
|
-
)
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Store only serializable hashes in the cache. After retrieval we recreate the pool objects and reattach the `has_server?` helper method.
|
|
35
|
-
Array(cached_pools).map do |pool|
|
|
36
|
-
OpenStruct.new(pool).tap do |pool_object|
|
|
37
|
-
pool_object.define_singleton_method(:has_server?) do |vmid|
|
|
38
|
-
Array(members).any? { |member| member[:vmid].to_s == vmid.to_s || member['vmid'].to_s == vmid.to_s }
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
23
|
+
pools = identity_client.pools.all
|
|
24
|
+
pools.sort_by(&:poolid)
|
|
42
25
|
end
|
|
43
26
|
|
|
44
27
|
def pool_owner(vm)
|
|
@@ -36,8 +36,6 @@ module ForemanFogProxmox
|
|
|
36
36
|
type = args[:type]
|
|
37
37
|
node = client.nodes.get(args[:node_id])
|
|
38
38
|
vmid = args[:vmid] = assign_vmid(args[:vmid].to_i, node)
|
|
39
|
-
raise ::Foreman::Exception, format(N_('invalid vmid=%<vmid>s'), vmid: vmid) unless node.servers.id_valid?(vmid)
|
|
40
|
-
|
|
41
39
|
image_id = args[:image_id]
|
|
42
40
|
remove_volume_keys(args)
|
|
43
41
|
if image_id
|
|
@@ -55,8 +53,15 @@ module ForemanFogProxmox
|
|
|
55
53
|
raise e
|
|
56
54
|
end
|
|
57
55
|
|
|
58
|
-
def assign_vmid(vmid, node)
|
|
59
|
-
|
|
56
|
+
def assign_vmid(vmid, node, log: true)
|
|
57
|
+
vmid = node.servers.next_id if vmid < 1
|
|
58
|
+
|
|
59
|
+
unless node.servers.id_valid?(vmid)
|
|
60
|
+
logger.warn("Requested VMID #{vmid} is occupied or out of range, requesting a new VMID") if log
|
|
61
|
+
vmid = node.servers.next_id
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
vmid
|
|
60
65
|
end
|
|
61
66
|
|
|
62
67
|
def compute_clone_attributes(args, container, type)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# rubocop:disable Metrics/ModuleLength
|
|
4
|
+
|
|
3
5
|
# Copyright 2019 Tristan Robert
|
|
4
6
|
|
|
5
7
|
# This file is part of ForemanFogProxmox.
|
|
@@ -97,7 +99,7 @@ module ForemanFogProxmox
|
|
|
97
99
|
end
|
|
98
100
|
|
|
99
101
|
def default_node
|
|
100
|
-
|
|
102
|
+
nodes.first
|
|
101
103
|
end
|
|
102
104
|
|
|
103
105
|
def default_node_id
|
|
@@ -182,10 +184,17 @@ module ForemanFogProxmox
|
|
|
182
184
|
config_attributes.delete_if { |key, _value| ['disks', 'interfaces'].include?(key) }
|
|
183
185
|
end
|
|
184
186
|
|
|
187
|
+
def assign_available_vmid(new_attr, node)
|
|
188
|
+
return if new_attr['vmid'].blank? || new_attr['node_id'].blank?
|
|
189
|
+
|
|
190
|
+
new_attr['vmid'] = assign_vmid(new_attr['vmid'].to_i, node, log: false)
|
|
191
|
+
end
|
|
192
|
+
|
|
185
193
|
def new_typed_vm(new_attr, type)
|
|
186
194
|
convert_config_attributes(new_attr) if new_attr.key?(:config_attributes)
|
|
187
195
|
node_id = new_attr['node_id']
|
|
188
196
|
node = node_id ? client.nodes.get(node_id) : default_node
|
|
197
|
+
assign_available_vmid(new_attr, node)
|
|
189
198
|
new_attr_type = new_attr['type']
|
|
190
199
|
new_attr_type ||= new_attr['config_attributes']['type'] if new_attr.key?('config_attributes')
|
|
191
200
|
new_attr_type ||= type
|
|
@@ -201,3 +210,5 @@ module ForemanFogProxmox
|
|
|
201
210
|
end
|
|
202
211
|
end
|
|
203
212
|
end
|
|
213
|
+
|
|
214
|
+
# rubocop:enable Metrics/ModuleLength
|
|
@@ -23,47 +23,29 @@ module ForemanFogProxmox
|
|
|
23
23
|
include ProxmoxVMUuidHelper
|
|
24
24
|
|
|
25
25
|
def nodes
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
nodes&.sort_by(&:node)&.map do |node|
|
|
29
|
-
{ node: node.node }
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
structs_from_cache(cached_nodes)
|
|
26
|
+
nodes = client.nodes.all if client
|
|
27
|
+
nodes&.sort_by(&:node)
|
|
34
28
|
end
|
|
35
29
|
|
|
36
30
|
def storages(node_id = default_node_id, type = 'images')
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
fields = [:storage, :enabled, :active, :content, :node_id, :avail, :used, :total]
|
|
43
|
-
extract_attributes(storage, fields).merge(identity: storage.storage)
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
structs_from_cache(cached_storages)
|
|
31
|
+
node = client.nodes.get node_id
|
|
32
|
+
node ||= default_node
|
|
33
|
+
storages = node.storages.list_by_content_type type
|
|
34
|
+
logger.debug("storages(): node_id #{node_id} type #{type}")
|
|
35
|
+
storages.reject { |s| s.enabled.to_i.zero? || s.active.to_i.zero? }.sort_by(&:storage)
|
|
48
36
|
end
|
|
49
37
|
|
|
50
38
|
def bridges(node_id = default_node_id)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
bridges.sort_by(&:iface).map do |bridge|
|
|
56
|
-
extract_attributes(bridge, [:iface, :node_id]).merge(identity: bridge.iface)
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
structs_from_cache(cached_bridges)
|
|
39
|
+
node = network_client.nodes.get node_id
|
|
40
|
+
node ||= network_client.nodes.first
|
|
41
|
+
bridges = node.networks.all(type: 'any_bridge')
|
|
42
|
+
bridges.sort_by(&:iface)
|
|
61
43
|
end
|
|
62
44
|
|
|
63
45
|
# TODO: Pagination with filters
|
|
64
46
|
def vms(opts = {})
|
|
65
47
|
vms = []
|
|
66
|
-
|
|
48
|
+
nodes.each { |node| vms += node.servers.all + node.containers.all }
|
|
67
49
|
vms.each { |vm| attach_compute_resource_id(vm) }
|
|
68
50
|
if opts.key?(:eager_loading) && opts[:eager_loading]
|
|
69
51
|
vms_eager = []
|
|
@@ -77,7 +59,7 @@ module ForemanFogProxmox
|
|
|
77
59
|
# look for the uuid on all known nodes
|
|
78
60
|
vm = nil
|
|
79
61
|
vmid = extract_vmid(uuid)
|
|
80
|
-
|
|
62
|
+
nodes.each do |node|
|
|
81
63
|
vm = find_vm_in_servers_by_vmid(node.servers, vmid)
|
|
82
64
|
vm ||= find_vm_in_servers_by_vmid(node.containers, vmid)
|
|
83
65
|
next if vm.nil?
|
|
@@ -100,11 +82,6 @@ module ForemanFogProxmox
|
|
|
100
82
|
|
|
101
83
|
private
|
|
102
84
|
|
|
103
|
-
def fog_nodes
|
|
104
|
-
nodes = client.nodes.all if client
|
|
105
|
-
nodes&.sort_by(&:node) || []
|
|
106
|
-
end
|
|
107
|
-
|
|
108
85
|
def attach_compute_resource_id(virtual_machine)
|
|
109
86
|
return virtual_machine if virtual_machine.nil?
|
|
110
87
|
|
|
@@ -36,8 +36,6 @@ along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>. %>
|
|
|
36
36
|
:wrapper_class => "form-group #{'hide' unless ssl_verify_peer}",
|
|
37
37
|
:placeholder => _("Optionally provide a CA, or a correctly ordered CA chain. If left blank, disable ssl_verify_peer.") %>
|
|
38
38
|
<% end %>
|
|
39
|
-
<%= checkbox_f f, :caching_enabled, :label => _("Enable Caching"),
|
|
40
|
-
:help_inline => _("Cache Proxmox resources.") %>
|
|
41
39
|
<div class="col-md-offset-2">
|
|
42
40
|
<%= test_connection_button_f(f, (f.object.nodes rescue true)) %>
|
|
43
41
|
</div>
|
|
@@ -19,6 +19,10 @@ along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>. %>
|
|
|
19
19
|
<td><%= _("URL") %></td>
|
|
20
20
|
<td><%= @compute_resource.url %></td>
|
|
21
21
|
</tr>
|
|
22
|
+
<tr>
|
|
23
|
+
<td><%= _("Username") %></td>
|
|
24
|
+
<td><%= @compute_resource.user %></td>
|
|
25
|
+
</tr>
|
|
22
26
|
<tr>
|
|
23
27
|
<td><%= _("Version") %></td>
|
|
24
28
|
<td><%= @compute_resource.version %></td>
|
|
@@ -27,10 +31,6 @@ along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>. %>
|
|
|
27
31
|
<td><%= _("Authentication method") %></td>
|
|
28
32
|
<td><%= @compute_resource.auth_method %></td>
|
|
29
33
|
</tr>
|
|
30
|
-
<tr>
|
|
31
|
-
<td><%= _("Caching") %></td>
|
|
32
|
-
<td><%= @compute_resource.caching_enabled ? _("Enabled") : _("Disabled") %></td>
|
|
33
|
-
</tr>
|
|
34
34
|
<tr>
|
|
35
35
|
<td><%= _("User token expires") %></td>
|
|
36
36
|
<td><%= user_token_expiration_date(@compute_resource) %></td>
|
|
@@ -43,17 +43,20 @@ module ForemanFogProxmox
|
|
|
43
43
|
parameter_filter(ComputeResource, :uuid)
|
|
44
44
|
# add dashboard widget
|
|
45
45
|
widget 'foreman_fog_proxmox_widget', name: N_('Foreman Fog Proxmox widget'), sizex: 8, sizey: 1
|
|
46
|
+
|
|
47
|
+
p = Foreman::AccessControl.permission(:view_compute_resources)
|
|
48
|
+
p.actions.concat(%w[foreman_fog_proxmox/compute_resources/ostemplates_by_id_and_node_and_storage
|
|
49
|
+
foreman_fog_proxmox/compute_resources/isos_by_id_and_node_and_storage
|
|
50
|
+
foreman_fog_proxmox/compute_resources/ostemplates_by_id_and_node
|
|
51
|
+
foreman_fog_proxmox/compute_resources/isos_by_id_and_node
|
|
52
|
+
foreman_fog_proxmox/compute_resources/storages_by_id_and_node
|
|
53
|
+
foreman_fog_proxmox/compute_resources/iso_storages_by_id_and_node
|
|
54
|
+
foreman_fog_proxmox/compute_resources/bridges_by_id_and_node
|
|
55
|
+
foreman_fog_proxmox/compute_resources/volumes_by_node_and_storage
|
|
56
|
+
foreman_fog_proxmox/compute_resources/metadata])
|
|
57
|
+
p.actions.uniq!
|
|
58
|
+
|
|
46
59
|
security_block :foreman_fog_proxmox do
|
|
47
|
-
permission :view_compute_resources, { :'foreman_fog_proxmox/compute_resources' =>
|
|
48
|
-
[:ostemplates_by_id_and_node_and_storage,
|
|
49
|
-
:isos_by_id_and_node_and_storage,
|
|
50
|
-
:ostemplates_by_id_and_node,
|
|
51
|
-
:isos_by_id_and_node,
|
|
52
|
-
:storages_by_id_and_node,
|
|
53
|
-
:iso_storages_by_id_and_node,
|
|
54
|
-
:bridges_by_id_and_node,
|
|
55
|
-
:volumes_by_node_and_storage,
|
|
56
|
-
:metadata] }
|
|
57
60
|
permission :attach_cdrom_image, {},
|
|
58
61
|
:resource_type => 'ComputeResource'
|
|
59
62
|
end
|
|
@@ -69,18 +69,6 @@ module ForemanFogProxmox
|
|
|
69
69
|
assert_not show_response.empty?
|
|
70
70
|
end
|
|
71
71
|
test 'should get volumes by node and storage' do
|
|
72
|
-
mock_storage = mock('storage')
|
|
73
|
-
mock_storage.stubs(:volumes).returns([])
|
|
74
|
-
mock_storages = mock('storages')
|
|
75
|
-
mock_storages.stubs(:get).with('local').returns(mock_storage)
|
|
76
|
-
mock_node = mock('node')
|
|
77
|
-
mock_node.stubs(:storages).returns(mock_storages)
|
|
78
|
-
mock_nodes = mock('nodes')
|
|
79
|
-
mock_nodes.stubs(:get).with('proxmox').returns(mock_node)
|
|
80
|
-
mock_client = mock('client')
|
|
81
|
-
mock_client.stubs(:nodes).returns(mock_nodes)
|
|
82
|
-
@compute_resource.stubs(:client).returns(mock_client)
|
|
83
|
-
|
|
84
72
|
get :volumes_by_node_and_storage,
|
|
85
73
|
params: { :compute_resource_id => @compute_resource.id, :node_id => 'proxmox', :storage => 'local' },
|
|
86
74
|
session: set_session_user
|
|
@@ -108,12 +108,6 @@ module ForemanFogProxmox
|
|
|
108
108
|
assert cr.update_required?(old_attrs, new_attrs)
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
-
test 'supports compute resource cache refreshing' do
|
|
112
|
-
cr = FactoryBot.build_stubbed(:proxmox_cr)
|
|
113
|
-
|
|
114
|
-
assert_respond_to cr, :refresh_cache
|
|
115
|
-
end
|
|
116
|
-
|
|
117
111
|
test '#node' do
|
|
118
112
|
node = mock('node')
|
|
119
113
|
cr = FactoryBot.build_stubbed(:proxmox_cr)
|
|
@@ -121,27 +115,6 @@ module ForemanFogProxmox
|
|
|
121
115
|
assert_equal node, (as_admin { cr.node })
|
|
122
116
|
end
|
|
123
117
|
|
|
124
|
-
test '#extract_attributes returns selected resource attributes' do
|
|
125
|
-
cr = FactoryBot.build_stubbed(:proxmox_cr)
|
|
126
|
-
|
|
127
|
-
resource = OpenStruct.new(
|
|
128
|
-
vmid: 101,
|
|
129
|
-
name: 'template-101',
|
|
130
|
-
ignored: 'ignored'
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
attributes = cr.send(:extract_attributes, resource, [:vmid, :name, :missing])
|
|
134
|
-
|
|
135
|
-
assert_equal(
|
|
136
|
-
{
|
|
137
|
-
vmid: 101,
|
|
138
|
-
name: 'template-101',
|
|
139
|
-
missing: nil,
|
|
140
|
-
},
|
|
141
|
-
attributes
|
|
142
|
-
)
|
|
143
|
-
end
|
|
144
|
-
|
|
145
118
|
private
|
|
146
119
|
|
|
147
120
|
def hdd_compute_attrs(volumes_attrs)
|
|
@@ -31,15 +31,18 @@ module ForemanFogProxmox
|
|
|
31
31
|
include ProxmoxVMHelper
|
|
32
32
|
|
|
33
33
|
describe 'create_vm' do
|
|
34
|
-
it '
|
|
35
|
-
args = { vmid: '100' }
|
|
34
|
+
it 'uses next vmid when requested vmid is occupied or out of range' do
|
|
35
|
+
args = { vmid: '100', type: 'qemu', node_id: 'proxmox', start_after_create: '0' }
|
|
36
36
|
servers = mock('servers')
|
|
37
|
-
servers.
|
|
37
|
+
servers.expects(:id_valid?).with(100).returns(false)
|
|
38
|
+
servers.expects(:next_id).returns('101')
|
|
38
39
|
cr = mock_node_servers(ForemanFogProxmox::Proxmox.new, servers)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
cr.stubs(:parse_typed_vm).with(args, 'qemu').returns(args)
|
|
41
|
+
vm = mock('vm')
|
|
42
|
+
servers.expects(:create).with(args).returns(vm)
|
|
43
|
+
cr.create_vm(args)
|
|
44
|
+
|
|
45
|
+
assert_equal '101', args[:vmid]
|
|
43
46
|
end
|
|
44
47
|
|
|
45
48
|
it 'computes next vmid when vmid == 0 and creates server' do
|
|
@@ -149,11 +149,11 @@ module ForemanFogProxmox
|
|
|
149
149
|
pools = mock('pools')
|
|
150
150
|
pool1 = mock('pool1')
|
|
151
151
|
pool1.stubs(:poolid).returns('pool1')
|
|
152
|
-
pool1.stubs(:
|
|
152
|
+
pool1.stubs(:has_server?).with('100').returns(true)
|
|
153
153
|
pool1.expects(:remove_server).with(uuid)
|
|
154
154
|
pool2 = mock('pool2')
|
|
155
155
|
pool2.stubs(:poolid).returns('pool2')
|
|
156
|
-
pool2.stubs(:
|
|
156
|
+
pool2.stubs(:has_server?).with('100').returns(false)
|
|
157
157
|
pool2.expects(:add_server).with(uuid)
|
|
158
158
|
pools.stubs(:all).returns([pool1, pool2])
|
|
159
159
|
pools.expects(:get).with('pool1').returns(pool1)
|
|
@@ -185,7 +185,7 @@ module ForemanFogProxmox
|
|
|
185
185
|
identity_client = mock('identity_client')
|
|
186
186
|
pools = mock('pools')
|
|
187
187
|
pool1 = mock('pool1')
|
|
188
|
-
pool1.stubs(:
|
|
188
|
+
pool1.stubs(:has_server?).with('100').returns(true)
|
|
189
189
|
pool1.stubs(:poolid).returns('pool1')
|
|
190
190
|
pool1.expects(:remove_server).with(uuid)
|
|
191
191
|
pools.stubs(:all).returns([pool1])
|
|
@@ -218,7 +218,7 @@ module ForemanFogProxmox
|
|
|
218
218
|
identity_client = mock('identity_client')
|
|
219
219
|
pools = mock('pools')
|
|
220
220
|
pool2 = mock('pool2')
|
|
221
|
-
pool2.stubs(:
|
|
221
|
+
pool2.stubs(:has_server?).with('100').returns(false)
|
|
222
222
|
pool2.stubs(:poolid).returns('pool2')
|
|
223
223
|
pool2.expects(:add_server).with(uuid)
|
|
224
224
|
pools.stubs(:all).returns([pool2])
|
|
@@ -39,5 +39,30 @@ module ForemanFogProxmox
|
|
|
39
39
|
assert cr.destroy_vm('abc')
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
|
+
|
|
43
|
+
describe 'assign_vmid' do
|
|
44
|
+
it 'uses next vmid when requested vmid is already occupied' do
|
|
45
|
+
cr = ForemanFogProxmox::Proxmox.new
|
|
46
|
+
servers = mock('servers')
|
|
47
|
+
node = mock('node')
|
|
48
|
+
node.stubs(:servers).returns(servers)
|
|
49
|
+
servers.expects(:id_valid?).with(100).returns(false)
|
|
50
|
+
servers.expects(:next_id).returns('101')
|
|
51
|
+
|
|
52
|
+
assert_equal '101', cr.assign_vmid(100, node)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'does not log when logging is disabled' do
|
|
56
|
+
cr = ForemanFogProxmox::Proxmox.new
|
|
57
|
+
servers = mock('servers')
|
|
58
|
+
node = mock('node')
|
|
59
|
+
node.stubs(:servers).returns(servers)
|
|
60
|
+
servers.expects(:id_valid?).with(100).returns(false)
|
|
61
|
+
servers.expects(:next_id).returns('101')
|
|
62
|
+
cr.logger.expects(:warn).never
|
|
63
|
+
|
|
64
|
+
assert_equal '101', cr.assign_vmid(100, node, log: false)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
42
67
|
end
|
|
43
68
|
end
|
|
@@ -111,5 +111,51 @@ module ForemanFogProxmox
|
|
|
111
111
|
assert_equal vm, @cr.new_vm(attr)
|
|
112
112
|
end
|
|
113
113
|
end
|
|
114
|
+
|
|
115
|
+
describe 'assign_available_vmid' do
|
|
116
|
+
before do
|
|
117
|
+
@cr = FactoryBot.build_stubbed(:proxmox_cr)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'uses next vmid when requested vmid is already occupied' do
|
|
121
|
+
attr = { 'vmid' => '100', 'node_id' => 'proxmox' }.with_indifferent_access
|
|
122
|
+
servers = mock('servers')
|
|
123
|
+
node = mock('node')
|
|
124
|
+
node.stubs(:servers).returns(servers)
|
|
125
|
+
servers.expects(:id_valid?).with(100).returns(false)
|
|
126
|
+
servers.expects(:next_id).returns('101')
|
|
127
|
+
@cr.logger.expects(:warn).never
|
|
128
|
+
|
|
129
|
+
@cr.assign_available_vmid(attr, node)
|
|
130
|
+
|
|
131
|
+
assert_equal '101', attr['vmid']
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it 'keeps requested vmid when it is available' do
|
|
135
|
+
attr = { 'vmid' => '100', 'node_id' => 'proxmox' }.with_indifferent_access
|
|
136
|
+
servers = mock('servers')
|
|
137
|
+
node = mock('node')
|
|
138
|
+
node.stubs(:servers).returns(servers)
|
|
139
|
+
servers.expects(:id_valid?).with(100).returns(true)
|
|
140
|
+
servers.expects(:next_id).never
|
|
141
|
+
|
|
142
|
+
@cr.assign_available_vmid(attr, node)
|
|
143
|
+
|
|
144
|
+
assert_equal 100, attr['vmid']
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it 'does not assign vmid when requested vmid is blank' do
|
|
148
|
+
attr = { 'vmid' => '', 'node_id' => 'proxmox' }.with_indifferent_access
|
|
149
|
+
servers = mock('servers')
|
|
150
|
+
node = mock('node')
|
|
151
|
+
node.stubs(:servers).returns(servers)
|
|
152
|
+
servers.expects(:id_valid?).never
|
|
153
|
+
servers.expects(:next_id).never
|
|
154
|
+
|
|
155
|
+
@cr.assign_available_vmid(attr, node)
|
|
156
|
+
|
|
157
|
+
assert_equal '', attr['vmid']
|
|
158
|
+
end
|
|
159
|
+
end
|
|
114
160
|
end
|
|
115
161
|
end
|
|
@@ -33,22 +33,6 @@ module ForemanFogProxmox
|
|
|
33
33
|
include ProxmoxContainerMockFactory
|
|
34
34
|
include ProxmoxVMHelper
|
|
35
35
|
|
|
36
|
-
describe 'nodes' do
|
|
37
|
-
it 'caches nodes for persisted compute resources' do
|
|
38
|
-
cr = FactoryBot.build_stubbed(:proxmox_cr, :caching_enabled => true)
|
|
39
|
-
node_z = OpenStruct.new(node: 'z-proxmox')
|
|
40
|
-
node_a = OpenStruct.new(node: 'a-proxmox')
|
|
41
|
-
nodes = mock('nodes')
|
|
42
|
-
nodes.expects(:all).once.returns([node_z, node_a])
|
|
43
|
-
client = mock('client')
|
|
44
|
-
client.stubs(:nodes).returns(nodes)
|
|
45
|
-
cr.stubs(:client).returns(client)
|
|
46
|
-
|
|
47
|
-
assert_equal %w[a-proxmox z-proxmox], cr.nodes.map(&:node)
|
|
48
|
-
assert_equal %w[a-proxmox z-proxmox], cr.nodes.map(&:node)
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
36
|
describe 'storages' do
|
|
53
37
|
before do
|
|
54
38
|
@cr = ForemanFogProxmox::Proxmox.new
|
|
@@ -66,11 +50,7 @@ module ForemanFogProxmox
|
|
|
66
50
|
active_storage = OpenStruct.new(storage: 'local', enabled: 1, active: 1)
|
|
67
51
|
@storages_collection.stubs(:list_by_content_type).with('images').returns([active_storage])
|
|
68
52
|
|
|
69
|
-
|
|
70
|
-
assert_equal 'local', storage.storage
|
|
71
|
-
assert_equal 1, storage.enabled
|
|
72
|
-
assert_equal 1, storage.active
|
|
73
|
-
assert_equal 'local', storage.identity
|
|
53
|
+
assert_equal [active_storage], @cr.storages('proxmox')
|
|
74
54
|
end
|
|
75
55
|
|
|
76
56
|
it 'returns active storages sorted by storage name' do
|
|
@@ -87,7 +67,7 @@ module ForemanFogProxmox
|
|
|
87
67
|
|
|
88
68
|
@storages_collection.stubs(:list_by_content_type).with('images').returns([valid, invalid])
|
|
89
69
|
|
|
90
|
-
assert_equal [
|
|
70
|
+
assert_equal [valid], @cr.storages('proxmox')
|
|
91
71
|
end
|
|
92
72
|
|
|
93
73
|
it 'excludes disabled storages (enabled=0)' do
|
|
@@ -117,45 +97,6 @@ module ForemanFogProxmox
|
|
|
117
97
|
|
|
118
98
|
assert_empty @cr.storages('proxmox')
|
|
119
99
|
end
|
|
120
|
-
|
|
121
|
-
it 'caches storages by node and content type for persisted compute resources' do
|
|
122
|
-
cr = FactoryBot.build_stubbed(:proxmox_cr, :caching_enabled => true)
|
|
123
|
-
active_storage = OpenStruct.new(storage: 'local', enabled: 1, active: 1)
|
|
124
|
-
storages_collection = mock('storages_collection')
|
|
125
|
-
storages_collection.expects(:list_by_content_type).with('images').once.returns([active_storage])
|
|
126
|
-
node = mock('node')
|
|
127
|
-
node.stubs(:storages).returns(storages_collection)
|
|
128
|
-
nodes = mock('nodes')
|
|
129
|
-
nodes.stubs(:get).with('proxmox').returns(node)
|
|
130
|
-
client = mock('client')
|
|
131
|
-
client.stubs(:nodes).returns(nodes)
|
|
132
|
-
cr.stubs(:client).returns(client)
|
|
133
|
-
|
|
134
|
-
assert_equal [active_storage.storage], cr.storages('proxmox').map(&:storage)
|
|
135
|
-
assert_equal [active_storage.storage], cr.storages('proxmox').map(&:storage)
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
it 'restores cached storages with normalized attributes' do
|
|
139
|
-
cr = FactoryBot.build_stubbed(:proxmox_cr, :caching_enabled => true)
|
|
140
|
-
active_storage = OpenStruct.new(storage: 'local', enabled: 1, active: 1)
|
|
141
|
-
storages_collection = mock('storages_collection')
|
|
142
|
-
storages_collection.expects(:list_by_content_type).with('images').once.returns([active_storage])
|
|
143
|
-
node = mock('node')
|
|
144
|
-
node.stubs(:storages).returns(storages_collection)
|
|
145
|
-
nodes = mock('nodes')
|
|
146
|
-
nodes.stubs(:get).with('proxmox').returns(node)
|
|
147
|
-
client = mock('client')
|
|
148
|
-
client.stubs(:nodes).returns(nodes)
|
|
149
|
-
cr.stubs(:client).returns(client)
|
|
150
|
-
|
|
151
|
-
cr.storages('proxmox')
|
|
152
|
-
cached_storage = cr.storages('proxmox').first
|
|
153
|
-
|
|
154
|
-
assert_equal 'local', cached_storage.storage
|
|
155
|
-
assert_equal 'local', cached_storage.identity
|
|
156
|
-
assert_equal [:active, :avail, :content, :enabled, :identity, :node_id, :storage, :total, :used],
|
|
157
|
-
cached_storage.to_h.keys.sort
|
|
158
|
-
end
|
|
159
100
|
end
|
|
160
101
|
|
|
161
102
|
describe 'find_vm_by_uuid' do
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { sprintf, translate as __ } from 'foremanReact/common/I18n';
|
|
2
2
|
|
|
3
|
+
// Unit selection uses a 1024 step (binary); the value is scaled by 1000 (decimal).
|
|
4
|
+
const BYTE_UNIT_STEP = 1024;
|
|
5
|
+
const BYTE_UNIT_DIVISOR = 1000;
|
|
6
|
+
|
|
3
7
|
const humanSize = size => {
|
|
4
|
-
const i = Math.floor(Math.log(size) / Math.log(
|
|
5
|
-
return `${(size /
|
|
8
|
+
const i = Math.floor(Math.log(size) / Math.log(BYTE_UNIT_STEP));
|
|
9
|
+
return `${(size / BYTE_UNIT_DIVISOR ** i).toFixed(2) * 1} ${
|
|
6
10
|
['B', 'kB', 'MB', 'GB', 'TB'][i]
|
|
7
11
|
}`;
|
|
8
12
|
};
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: foreman_fog_proxmox
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.25.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tristan Robert
|
|
@@ -325,7 +325,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
325
325
|
- !ruby/object:Gem::Version
|
|
326
326
|
version: '0'
|
|
327
327
|
requirements: []
|
|
328
|
-
rubygems_version: 4.0.
|
|
328
|
+
rubygems_version: 4.0.16
|
|
329
329
|
specification_version: 4
|
|
330
330
|
summary: Foreman plugin that adds Proxmox VE compute resource using fog-proxmox
|
|
331
331
|
test_files:
|