fog-proxmox 1.0.0 → 1.1.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/CHANGELOG.md +13 -0
- data/README.md +4 -4
- data/lib/fog/proxmox/compute/models/rng.rb +35 -0
- data/lib/fog/proxmox/compute/models/server_config.rb +14 -1
- data/lib/fog/proxmox/compute.rb +1 -0
- data/lib/fog/proxmox/helpers/agent_helper.rb +50 -0
- data/lib/fog/proxmox/helpers/hotplug_helper.rb +41 -0
- data/lib/fog/proxmox/helpers/rng_helper.rb +61 -0
- data/lib/fog/proxmox/storage/models/iso_upload.rb +3 -2
- data/lib/fog/proxmox/version.rb +1 -1
- data/spec/fog/proxmox/storage/storage_upload_iso_spec.rb +29 -8
- data/spec/helpers/agent_helper_spec.rb +66 -0
- data/spec/helpers/hotplug_helper_spec.rb +67 -0
- data/spec/helpers/rng_helper_spec.rb +108 -0
- metadata +8 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d571150b56652b8f22fc3172ac26caf7918bdc167c5202b9f0809f138693da0f
|
|
4
|
+
data.tar.gz: f26c7b0f98d625306b573bdc2c848974438b03260ac7814b796d055e9967c88a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: df89614d08202bce01cc9f9be6d0fe3bd03a763672016ef363a0666a70e08625c6babed6d5969344496334d1aa5f59ef9584bf4e10b1b8f1b39a60d648d8b3b0
|
|
7
|
+
data.tar.gz: 4fea613dea946a99e5376f6b691eaf6112c1f21d8116497a44e0cc67aba0ddb081a766941b9a1fb8922e40160e451791984a2c06176670fce9f979556fc730bd
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.1.0](https://github.com/fog/fog-proxmox/compare/v1.0.0...v1.1.0) (2026-10-21)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* Add hotplug support ([#158](https://github.com/fog/fog-proxmox/issues/158)) ([0745f60](https://github.com/fog/fog-proxmox/commit/0745f6013003af9d0b1ec7304749a5c52038fa62))
|
|
9
|
+
* Add VirtIO RNG device support ([#160](https://github.com/fog/fog-proxmox/issues/160)) ([a31b9d3](https://github.com/fog/fog-proxmox/commit/a31b9d39927d82b2db9da6c1889b9fd556905b5c))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* ISO upload task polling ([3dc3c31](https://github.com/fog/fog-proxmox/commit/3dc3c31fe8cd72fc719954917dad39afa6b08ebd))
|
|
15
|
+
|
|
3
16
|
## [1.0.0](https://github.com/fog/fog-proxmox/compare/v0.16.2...v1.0.0) (2026-09-14)
|
|
4
17
|
|
|
5
18
|
|
data/README.md
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
# Fog::Proxmox
|
|
4
4
|
|
|
5
|
-
](https://github.com/fog/fog-proxmox/actions/workflows/ci.yml)
|
|
6
6
|
[](https://codeclimate.com/github/fog/fog-proxmox/maintainability)
|
|
7
7
|
[](https://codeclimate.com/github/fog/fog-proxmox/test_coverage)
|
|
8
8
|
[](https://badge.fury.io/rb/fog-proxmox)
|
|
9
9
|
|
|
10
|
-
This is a [FOG](
|
|
10
|
+
This is a [FOG](https://fog.github.io/) (>= 2.1) module gem to support [Proxmox VE](https://www.proxmox.com/en/proxmox-ve)
|
|
11
11
|
|
|
12
|
-
It is intended to satisfy this [feature](https://github.com/fog/fog/issues/3644), but Proxmox provider only, and above all this [Foreman](
|
|
12
|
+
It is intended to satisfy this [feature](https://github.com/fog/fog/issues/3644), but Proxmox provider only, and above all this [Foreman](https://www.theforeman.org) [feature](https://projects.theforeman.org/issues/2186).
|
|
13
13
|
|
|
14
14
|
It is inspired by the great [fog-openstack](https://github.com/fog/fog-openstack) module.
|
|
15
15
|
|
|
@@ -102,7 +102,7 @@ bundle exec rake --tasks
|
|
|
102
102
|
## Contributing
|
|
103
103
|
|
|
104
104
|
You can reach the [contributors](.github/CONTRIBUTORS.md).
|
|
105
|
-
Bug reports and pull requests are welcome on GitHub at [Fog-Proxmox](https://github.com/fog/fog-proxmox/issues). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](
|
|
105
|
+
Bug reports and pull requests are welcome on GitHub at [Fog-Proxmox](https://github.com/fog/fog-proxmox/issues). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](https://www.contributor-covenant.org) code of conduct.
|
|
106
106
|
|
|
107
107
|
Please read [how to contribute](.github/CONTRIBUTING.md).
|
|
108
108
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file is part of Fog::Proxmox.
|
|
4
|
+
|
|
5
|
+
# Fog::Proxmox is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# Fog::Proxmox is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Fog::Proxmox. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require 'fog/proxmox/helpers/rng_helper'
|
|
19
|
+
|
|
20
|
+
module Fog
|
|
21
|
+
module Proxmox
|
|
22
|
+
class Compute
|
|
23
|
+
# VirtIO RNG device; period is in milliseconds and max_bytes is in bytes.
|
|
24
|
+
class Rng < Fog::Model
|
|
25
|
+
attribute :max_bytes
|
|
26
|
+
attribute :period
|
|
27
|
+
attribute :source
|
|
28
|
+
|
|
29
|
+
def flatten
|
|
30
|
+
Fog::Proxmox::RngHelper.flatten(attributes)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -21,6 +21,7 @@ require 'fog/proxmox/attributes'
|
|
|
21
21
|
require 'fog/proxmox/helpers/nic_helper'
|
|
22
22
|
require 'fog/proxmox/helpers/controller_helper'
|
|
23
23
|
require 'fog/proxmox/helpers/efidisk_helper'
|
|
24
|
+
require 'fog/proxmox/helpers/rng_helper'
|
|
24
25
|
|
|
25
26
|
module Fog
|
|
26
27
|
module Proxmox
|
|
@@ -41,6 +42,7 @@ module Fog
|
|
|
41
42
|
attribute :onboot
|
|
42
43
|
attribute :boot
|
|
43
44
|
attribute :agent
|
|
45
|
+
attribute :hotplug
|
|
44
46
|
attribute :scsihw
|
|
45
47
|
attribute :sockets
|
|
46
48
|
attribute :memory
|
|
@@ -80,6 +82,7 @@ module Fog
|
|
|
80
82
|
attribute :searchdomain
|
|
81
83
|
attribute :nameserver
|
|
82
84
|
attribute :efidisk
|
|
85
|
+
attribute :rng
|
|
83
86
|
|
|
84
87
|
def initialize(new_attributes = {})
|
|
85
88
|
prepare_service_value(new_attributes)
|
|
@@ -88,6 +91,7 @@ module Fog
|
|
|
88
91
|
initialize_interfaces(new_attributes)
|
|
89
92
|
initialize_disks(new_attributes)
|
|
90
93
|
initialize_efidisk(new_attributes)
|
|
94
|
+
initialize_rng(new_attributes)
|
|
91
95
|
super(new_attributes)
|
|
92
96
|
end
|
|
93
97
|
|
|
@@ -103,9 +107,10 @@ module Fog
|
|
|
103
107
|
end
|
|
104
108
|
|
|
105
109
|
def flatten
|
|
106
|
-
flat_hash = attributes.reject { |attribute| %i[node_id type vmid disks interfaces].include? attribute }
|
|
110
|
+
flat_hash = attributes.reject { |attribute| %i[node_id type vmid disks interfaces rng].include? attribute }
|
|
107
111
|
flat_hash.merge(interfaces_flatten)
|
|
108
112
|
flat_hash.merge(disks_flatten)
|
|
113
|
+
flat_hash.merge!(rng.flatten) unless rng.nil?
|
|
109
114
|
flat_hash
|
|
110
115
|
end
|
|
111
116
|
|
|
@@ -166,6 +171,14 @@ module Fog
|
|
|
166
171
|
efidisk_hash = Fog::Proxmox::EfidiskHelper.extract(efidisk)
|
|
167
172
|
attributes[:efidisk] = Fog::Proxmox::Compute::Efidisk.new(efidisk_hash)
|
|
168
173
|
end
|
|
174
|
+
|
|
175
|
+
def initialize_rng(new_attributes)
|
|
176
|
+
rng = new_attributes[:rng0] || new_attributes['rng0']
|
|
177
|
+
return if rng.nil?
|
|
178
|
+
|
|
179
|
+
rng_hash = Fog::Proxmox::RngHelper.extract(rng)
|
|
180
|
+
attributes[:rng] = Fog::Proxmox::Compute::Rng.new(rng_hash)
|
|
181
|
+
end
|
|
169
182
|
end
|
|
170
183
|
end
|
|
171
184
|
end
|
data/lib/fog/proxmox/compute.rb
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file is part of Fog::Proxmox.
|
|
4
|
+
|
|
5
|
+
# Fog::Proxmox is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# Fog::Proxmox is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Fog::Proxmox. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
module Fog
|
|
19
|
+
module Proxmox
|
|
20
|
+
# Convert guest agent settings to and from Proxmox configuration strings.
|
|
21
|
+
module AgentHelper
|
|
22
|
+
DEFAULTS = {
|
|
23
|
+
'enabled' => '0',
|
|
24
|
+
'freeze-fs-on-backup' => '1',
|
|
25
|
+
'fstrim_cloned_disks' => '0',
|
|
26
|
+
'type' => 'virtio'
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
29
|
+
def self.extract(agent)
|
|
30
|
+
settings = DEFAULTS.dup
|
|
31
|
+
agent.to_s.split(',').each do |option|
|
|
32
|
+
key, value = option.split('=', 2)
|
|
33
|
+
if value.nil?
|
|
34
|
+
settings['enabled'] = key
|
|
35
|
+
else
|
|
36
|
+
settings[key] = value
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
settings['freeze-fs-on-backup'] = settings.fetch('freeze-fs', settings['freeze-fs-on-backup'])
|
|
41
|
+
settings
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.flatten(settings)
|
|
45
|
+
"enabled=#{settings['enabled']},freeze-fs-on-backup=#{settings['freeze-fs-on-backup']}," \
|
|
46
|
+
"fstrim_cloned_disks=#{settings['fstrim_cloned_disks']},type=#{settings['type']}"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file is part of Fog::Proxmox.
|
|
4
|
+
|
|
5
|
+
# Fog::Proxmox is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# Fog::Proxmox is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Fog::Proxmox. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
module Fog
|
|
19
|
+
module Proxmox
|
|
20
|
+
# Convert hotplug settings to and from Proxmox configuration strings.
|
|
21
|
+
module HotplugHelper
|
|
22
|
+
DEVICES = %w[disk network usb cpu memory].freeze
|
|
23
|
+
DEFAULTS = %w[disk network usb].freeze
|
|
24
|
+
|
|
25
|
+
def self.extract(hotplug)
|
|
26
|
+
hotplug = hotplug.to_s
|
|
27
|
+
{
|
|
28
|
+
enabled: hotplug != '0',
|
|
29
|
+
devices: hotplug.empty? || hotplug == '1' ? DEFAULTS.dup : hotplug.split(',')
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.flatten(settings)
|
|
34
|
+
return '0' unless settings[:enabled]
|
|
35
|
+
|
|
36
|
+
devices = DEVICES.select { |device| settings[:devices].include?(device) }
|
|
37
|
+
devices.empty? ? '0' : devices.join(',')
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file is part of Fog::Proxmox.
|
|
4
|
+
|
|
5
|
+
# Fog::Proxmox is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# Fog::Proxmox is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Fog::Proxmox. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require 'fog/proxmox/hash'
|
|
19
|
+
|
|
20
|
+
module Fog
|
|
21
|
+
module Proxmox
|
|
22
|
+
# Convert RNG devices to and from Proxmox configuration strings
|
|
23
|
+
module RngHelper
|
|
24
|
+
RNG_SOURCES = %w[/dev/urandom /dev/random /dev/hwrng].freeze
|
|
25
|
+
|
|
26
|
+
def self.flatten(rng)
|
|
27
|
+
return {} if rng.nil?
|
|
28
|
+
|
|
29
|
+
options = rng.select do |key, value|
|
|
30
|
+
%i[max_bytes period source].include?(key) && !value.nil? && value != ''
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
validate(options)
|
|
34
|
+
|
|
35
|
+
{ rng0: Fog::Proxmox::Hash.stringify(options) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.validate(rng)
|
|
39
|
+
raise ArgumentError, 'RNG source is required and must be /dev/urandom, /dev/random, or /dev/hwrng' unless RNG_SOURCES.include?(rng[:source].to_s)
|
|
40
|
+
|
|
41
|
+
%i[max_bytes period].each do |key|
|
|
42
|
+
next if rng[key].nil? || rng[key] == ''
|
|
43
|
+
next if rng[key].to_s.match?(/\A[0-9]+\z/)
|
|
44
|
+
|
|
45
|
+
raise ArgumentError, "RNG #{key} must be a non-negative integer"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.extract(rng)
|
|
52
|
+
options = rng.split(',').each_with_object({}) do |option, values|
|
|
53
|
+
key, value = option.split('=', 2)
|
|
54
|
+
values[key.to_sym] = value&.sub(/\A"(.*)"\z/, '\1')
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
options.slice(:max_bytes, :period, :source)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -22,9 +22,10 @@ module Fog
|
|
|
22
22
|
)
|
|
23
23
|
end
|
|
24
24
|
Fog::Logger.debug("Upload response: #{response.inspect}")
|
|
25
|
-
|
|
25
|
+
task_node = response.to_s[/\AUPID:([^:]+):/, 1]
|
|
26
|
+
raise Fog::Errors::Error, "Unexpected upload response: #{response.inspect}" unless task_node
|
|
26
27
|
|
|
27
|
-
service.nodes.get(
|
|
28
|
+
service.nodes.get(task_node).tasks.wait_for(response)
|
|
28
29
|
response
|
|
29
30
|
end
|
|
30
31
|
end
|
data/lib/fog/proxmox/version.rb
CHANGED
|
@@ -13,6 +13,7 @@ describe Fog::Proxmox::Compute::Storage do # rubocop:disable RSpec/SpecFilePathF
|
|
|
13
13
|
let(:upload_service) { Minitest::Mock.new }
|
|
14
14
|
let(:storage) { storage_class.new(service: service, node_id: 'pve', storage: 'local') }
|
|
15
15
|
let(:iso) { Tempfile.new(['cloudinit', '.iso']) }
|
|
16
|
+
let(:upload_upid) { 'UPID:pve:000008D8:00009E0D:5FBE5DEC:imgcopy::root@pam:' }
|
|
16
17
|
|
|
17
18
|
attr_accessor :uploaded_file
|
|
18
19
|
|
|
@@ -28,11 +29,11 @@ describe Fog::Proxmox::Compute::Storage do # rubocop:disable RSpec/SpecFilePathF
|
|
|
28
29
|
iso.close!
|
|
29
30
|
end
|
|
30
31
|
|
|
31
|
-
def expect_upload(response, error: nil)
|
|
32
|
+
def expect_upload(response, error: nil, node: 'pve')
|
|
32
33
|
service.expect(:nil?, false)
|
|
33
34
|
service.expect(:config, :compute_config)
|
|
34
35
|
upload_service.expect(:upload_iso, response) do |path, body|
|
|
35
|
-
_(path).must_equal(node:
|
|
36
|
+
_(path).must_equal(node: node, storage: 'local')
|
|
36
37
|
_(body[:filename]).must_equal File.basename(iso.path)
|
|
37
38
|
self.uploaded_file = body[:file]
|
|
38
39
|
_(uploaded_file.read).must_equal "cloud-init\x00\xFF".b
|
|
@@ -54,27 +55,38 @@ describe Fog::Proxmox::Compute::Storage do # rubocop:disable RSpec/SpecFilePathF
|
|
|
54
55
|
upload_service.verify
|
|
55
56
|
end
|
|
56
57
|
|
|
57
|
-
def expect_wait(error: nil)
|
|
58
|
+
def expect_wait(error: nil, node: 'pve', expected_upid: upload_upid)
|
|
58
59
|
tasks = Object.new
|
|
59
60
|
test = self
|
|
60
61
|
tasks.define_singleton_method(:wait_for) do |upid|
|
|
61
|
-
test.assert_equal
|
|
62
|
+
test.assert_equal expected_upid, upid
|
|
62
63
|
test.assert_predicate test.uploaded_file, :closed?
|
|
63
64
|
raise error if error
|
|
64
65
|
|
|
65
66
|
true
|
|
66
67
|
end
|
|
67
68
|
nodes = Minitest::Mock.new
|
|
68
|
-
nodes.expect(:get, Struct.new(:tasks).new(tasks), [
|
|
69
|
+
nodes.expect(:get, Struct.new(:tasks).new(tasks), [node])
|
|
69
70
|
service.expect(:nodes, nodes)
|
|
70
71
|
nodes
|
|
71
72
|
end
|
|
72
73
|
|
|
73
74
|
it 'uploads to its node and storage, closes the file, and waits before returning the UPID' do
|
|
74
|
-
expect_upload(
|
|
75
|
+
expect_upload(upload_upid)
|
|
75
76
|
nodes = expect_wait
|
|
76
77
|
|
|
77
|
-
_(upload_iso).must_equal
|
|
78
|
+
_(upload_iso).must_equal upload_upid
|
|
79
|
+
service.verify
|
|
80
|
+
nodes.verify
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'polls the node in the returned UPID when it differs from the upload node' do
|
|
84
|
+
storage.node_id = 'test-2'
|
|
85
|
+
upid = 'UPID:test-1:000008D8:00009E0D:5FBE5DEC:upload::root@pam:'
|
|
86
|
+
expect_upload(upid, node: 'test-2')
|
|
87
|
+
nodes = expect_wait(node: 'test-1', expected_upid: upid)
|
|
88
|
+
|
|
89
|
+
_(upload_iso).must_equal upid
|
|
78
90
|
service.verify
|
|
79
91
|
nodes.verify
|
|
80
92
|
end
|
|
@@ -88,6 +100,15 @@ describe Fog::Proxmox::Compute::Storage do # rubocop:disable RSpec/SpecFilePathF
|
|
|
88
100
|
service.verify
|
|
89
101
|
end
|
|
90
102
|
|
|
103
|
+
it 'rejects a UPID with no task owner without polling tasks' do
|
|
104
|
+
expect_upload('UPID::000008D8:00009E0D:5FBE5DEC:imgcopy::root@pam:')
|
|
105
|
+
|
|
106
|
+
error = _(proc { upload_iso }).must_raise Fog::Errors::Error
|
|
107
|
+
_(error.message).must_match(/Unexpected upload response/)
|
|
108
|
+
_(uploaded_file.closed?).must_equal true
|
|
109
|
+
service.verify
|
|
110
|
+
end
|
|
111
|
+
|
|
91
112
|
it 'closes the file when the upload request fails' do
|
|
92
113
|
expect_upload(nil, error: Fog::Errors::Error.new('Upload failed'))
|
|
93
114
|
|
|
@@ -97,7 +118,7 @@ describe Fog::Proxmox::Compute::Storage do # rubocop:disable RSpec/SpecFilePathF
|
|
|
97
118
|
end
|
|
98
119
|
|
|
99
120
|
it 'propagates task failures' do
|
|
100
|
-
expect_upload(
|
|
121
|
+
expect_upload(upload_upid)
|
|
101
122
|
nodes = expect_wait(error: Fog::Errors::Error.new('Task failed'))
|
|
102
123
|
|
|
103
124
|
error = _(proc { upload_iso }).must_raise Fog::Errors::Error
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file is part of Fog::Proxmox.
|
|
4
|
+
|
|
5
|
+
# Fog::Proxmox is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# Fog::Proxmox is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Fog::Proxmox. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require 'spec_helper'
|
|
19
|
+
require 'fog/proxmox/helpers/agent_helper'
|
|
20
|
+
|
|
21
|
+
describe 'AgentHelper' do
|
|
22
|
+
describe '.extract' do
|
|
23
|
+
[nil, '', '0', 0].each do |agent|
|
|
24
|
+
it "uses disabled defaults for #{agent.inspect}" do
|
|
25
|
+
assert_equal Fog::Proxmox::AgentHelper::DEFAULTS, Fog::Proxmox::AgentHelper.extract(agent)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
['1', 1, 'enabled=1'].each do |agent|
|
|
30
|
+
it "reads enabled shorthand #{agent.inspect}" do
|
|
31
|
+
expected = Fog::Proxmox::AgentHelper::DEFAULTS.merge('enabled' => '1')
|
|
32
|
+
assert_equal expected, Fog::Proxmox::AgentHelper.extract(agent)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'reads explicit options even when disabled' do
|
|
37
|
+
settings = Fog::Proxmox::AgentHelper.extract('enabled=0,freeze-fs-on-backup=0,fstrim_cloned_disks=1,type=isa')
|
|
38
|
+
assert_equal({ 'enabled' => '0', 'freeze-fs-on-backup' => '0', 'fstrim_cloned_disks' => '1', 'type' => 'isa' }, settings)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'prefers freeze-fs regardless of option order' do
|
|
42
|
+
['freeze-fs=0,freeze-fs-on-backup=1', 'freeze-fs-on-backup=1,freeze-fs=0'].each do |options|
|
|
43
|
+
assert_equal '0', Fog::Proxmox::AgentHelper.extract("1,#{options}")['freeze-fs-on-backup']
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'splits option values at only the first equals sign' do
|
|
48
|
+
assert_equal 'a=b', Fog::Proxmox::AgentHelper.extract('type=a=b')['type']
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'returns independent settings without changing defaults' do
|
|
52
|
+
Fog::Proxmox::AgentHelper.extract(nil)['enabled'] = '1'
|
|
53
|
+
assert_equal '0', Fog::Proxmox::AgentHelper.extract(nil)['enabled']
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '.flatten' do
|
|
58
|
+
%w[0 1].each do |enabled|
|
|
59
|
+
it "serializes all options with enabled=#{enabled}" do
|
|
60
|
+
settings = { 'enabled' => enabled, 'freeze-fs-on-backup' => '0', 'fstrim_cloned_disks' => '1', 'type' => 'isa' }
|
|
61
|
+
assert_equal "enabled=#{enabled},freeze-fs-on-backup=0,fstrim_cloned_disks=1,type=isa", Fog::Proxmox::AgentHelper.flatten(settings)
|
|
62
|
+
assert_equal settings, Fog::Proxmox::AgentHelper.extract(Fog::Proxmox::AgentHelper.flatten(settings))
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file is part of Fog::Proxmox.
|
|
4
|
+
|
|
5
|
+
# Fog::Proxmox is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# Fog::Proxmox is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Fog::Proxmox. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require 'spec_helper'
|
|
19
|
+
require 'fog/proxmox/helpers/hotplug_helper'
|
|
20
|
+
|
|
21
|
+
describe 'HotplugHelper' do
|
|
22
|
+
describe '.extract' do
|
|
23
|
+
[nil, '', '1', 1].each do |hotplug|
|
|
24
|
+
it "uses enabled default devices for #{hotplug.inspect}" do
|
|
25
|
+
assert_equal({ enabled: true, devices: %w[disk network usb] }, Fog::Proxmox::HotplugHelper.extract(hotplug))
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
['0', 0].each do |hotplug|
|
|
30
|
+
it "disables hotplug for #{hotplug.inspect}" do
|
|
31
|
+
settings = Fog::Proxmox::HotplugHelper.extract(hotplug)
|
|
32
|
+
assert_equal false, settings[:enabled]
|
|
33
|
+
assert_empty Fog::Proxmox::HotplugHelper::DEVICES & settings[:devices]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'reads an explicit device list' do
|
|
38
|
+
assert_equal({ enabled: true, devices: %w[disk cpu memory] }, Fog::Proxmox::HotplugHelper.extract('disk,cpu,memory'))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'returns an independent default device list' do
|
|
42
|
+
Fog::Proxmox::HotplugHelper.extract(nil)[:devices].clear
|
|
43
|
+
assert_equal %w[disk network usb], Fog::Proxmox::HotplugHelper.extract(nil)[:devices]
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe '.flatten' do
|
|
48
|
+
it 'serializes selected devices in the existing device order' do
|
|
49
|
+
assert_equal 'disk,network,cpu', Fog::Proxmox::HotplugHelper.flatten(enabled: true, devices: %w[cpu network disk])
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'disables hotplug even when devices are selected' do
|
|
53
|
+
assert_equal '0', Fog::Proxmox::HotplugHelper.flatten(enabled: false, devices: %w[disk network])
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'disables hotplug when no supported devices are selected' do
|
|
57
|
+
[[], ['unknown']].each do |devices|
|
|
58
|
+
assert_equal '0', Fog::Proxmox::HotplugHelper.flatten(enabled: true, devices: devices)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'round trips explicit supported devices' do
|
|
63
|
+
raw = 'disk,cpu,memory'
|
|
64
|
+
assert_equal raw, Fog::Proxmox::HotplugHelper.flatten(Fog::Proxmox::HotplugHelper.extract(raw))
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file is part of Fog::Proxmox.
|
|
4
|
+
|
|
5
|
+
# Fog::Proxmox is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# Fog::Proxmox is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Fog::Proxmox. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require 'spec_helper'
|
|
19
|
+
require 'fog/proxmox/helpers/rng_helper'
|
|
20
|
+
|
|
21
|
+
rng_helper_class = Fog::Proxmox::RngHelper
|
|
22
|
+
|
|
23
|
+
describe Fog::Proxmox::RngHelper do
|
|
24
|
+
let(:rng_value) { 'max_bytes=1024,period=2000,source=/dev/urandom' }
|
|
25
|
+
let(:rng_attributes) { { max_bytes: '1024', period: '2000', source: '/dev/urandom' } }
|
|
26
|
+
|
|
27
|
+
it 'extracts all RNG options' do
|
|
28
|
+
assert_equal rng_attributes, rng_helper_class.extract(rng_value)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'extracts options regardless of their order' do
|
|
32
|
+
assert_equal rng_attributes,
|
|
33
|
+
rng_helper_class.extract('source=/dev/urandom,period=2000,max_bytes=1024')
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'extracts a quoted period without the surrounding quotes' do
|
|
37
|
+
assert_equal rng_attributes,
|
|
38
|
+
rng_helper_class.extract('source=/dev/urandom,max_bytes=1024,period="2000"')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'extracts quoted values for all RNG options' do
|
|
42
|
+
assert_equal rng_attributes,
|
|
43
|
+
rng_helper_class.extract('max_bytes="1024",period="2000",source="/dev/urandom"')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'extracts a source without optional rate limits' do
|
|
47
|
+
assert_equal({ source: '/dev/hwrng' },
|
|
48
|
+
rng_helper_class.extract('source=/dev/hwrng'))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'ignores unsupported options when extracting' do
|
|
52
|
+
assert_equal({ source: '/dev/urandom' },
|
|
53
|
+
rng_helper_class.extract('source=/dev/urandom,unknown=value'))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'flattens all RNG options' do
|
|
57
|
+
assert_equal({ rng0: rng_value }, rng_helper_class.flatten(rng_attributes))
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'accepts each supported RNG source' do
|
|
61
|
+
%w[/dev/urandom /dev/random /dev/hwrng].each do |source|
|
|
62
|
+
assert_equal({ rng0: "source=#{source}" }, rng_helper_class.flatten(source: source))
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'requires a source when configuring an RNG device' do
|
|
67
|
+
[{}, { max_bytes: 1024 }, { source: nil }, { source: '' }].each do |attributes|
|
|
68
|
+
error = assert_raises(ArgumentError) { rng_helper_class.flatten(attributes) }
|
|
69
|
+
assert_match(/RNG source is required/, error.message)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'rejects unsupported or partially matching source paths' do
|
|
74
|
+
['/dev/null', '/dev/random/extra', 'prefix/dev/urandom', "/dev/hwrng\n", ' '].each do |source|
|
|
75
|
+
assert_raises(ArgumentError) { rng_helper_class.flatten(source: source) }
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'accepts integer rate limits' do
|
|
80
|
+
assert_equal({ rng0: rng_value },
|
|
81
|
+
rng_helper_class.flatten(max_bytes: 1024, period: 2000, source: '/dev/urandom'))
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
%i[max_bytes period].each do |key|
|
|
85
|
+
it "rejects invalid #{key} values" do
|
|
86
|
+
['abc', '1024bytes', '1.5', 1.5, -1, '-1', true, ' ', "1024\n"].each do |value|
|
|
87
|
+
error = assert_raises(ArgumentError) do
|
|
88
|
+
rng_helper_class.flatten(source: '/dev/urandom', key => value)
|
|
89
|
+
end
|
|
90
|
+
assert_equal "RNG #{key} must be a non-negative integer", error.message
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'omits unset options and retains zero values' do
|
|
96
|
+
assert_equal({ rng0: 'max_bytes=0,source=/dev/random' },
|
|
97
|
+
rng_helper_class.flatten(max_bytes: 0, period: nil, source: '/dev/random'))
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'omits blank limits and unsupported options' do
|
|
101
|
+
assert_equal({ rng0: 'source=/dev/urandom' },
|
|
102
|
+
rng_helper_class.flatten(max_bytes: '', period: '', source: '/dev/urandom', unknown: 'value'))
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it 'returns an empty hash for a missing device' do
|
|
106
|
+
assert_empty rng_helper_class.flatten(nil)
|
|
107
|
+
end
|
|
108
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fog-proxmox
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tristan Robert
|
|
@@ -9,20 +9,6 @@ bindir: bin
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
-
- !ruby/object:Gem::Dependency
|
|
13
|
-
name: bundler
|
|
14
|
-
requirement: !ruby/object:Gem::Requirement
|
|
15
|
-
requirements:
|
|
16
|
-
- - ">="
|
|
17
|
-
- !ruby/object:Gem::Version
|
|
18
|
-
version: '2.1'
|
|
19
|
-
type: :development
|
|
20
|
-
prerelease: false
|
|
21
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
-
requirements:
|
|
23
|
-
- - ">="
|
|
24
|
-
- !ruby/object:Gem::Version
|
|
25
|
-
version: '2.1'
|
|
26
12
|
- !ruby/object:Gem::Dependency
|
|
27
13
|
name: bundler-audit
|
|
28
14
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -264,6 +250,7 @@ files:
|
|
|
264
250
|
- lib/fog/proxmox/compute/models/multipart_iso_upload.rb
|
|
265
251
|
- lib/fog/proxmox/compute/models/node.rb
|
|
266
252
|
- lib/fog/proxmox/compute/models/nodes.rb
|
|
253
|
+
- lib/fog/proxmox/compute/models/rng.rb
|
|
267
254
|
- lib/fog/proxmox/compute/models/server.rb
|
|
268
255
|
- lib/fog/proxmox/compute/models/server_config.rb
|
|
269
256
|
- lib/fog/proxmox/compute/models/servers.rb
|
|
@@ -315,12 +302,15 @@ files:
|
|
|
315
302
|
- lib/fog/proxmox/core.rb
|
|
316
303
|
- lib/fog/proxmox/errors.rb
|
|
317
304
|
- lib/fog/proxmox/hash.rb
|
|
305
|
+
- lib/fog/proxmox/helpers/agent_helper.rb
|
|
318
306
|
- lib/fog/proxmox/helpers/controller_helper.rb
|
|
319
307
|
- lib/fog/proxmox/helpers/cpu_helper.rb
|
|
320
308
|
- lib/fog/proxmox/helpers/disk_helper.rb
|
|
321
309
|
- lib/fog/proxmox/helpers/efidisk_helper.rb
|
|
310
|
+
- lib/fog/proxmox/helpers/hotplug_helper.rb
|
|
322
311
|
- lib/fog/proxmox/helpers/ip_helper.rb
|
|
323
312
|
- lib/fog/proxmox/helpers/nic_helper.rb
|
|
313
|
+
- lib/fog/proxmox/helpers/rng_helper.rb
|
|
324
314
|
- lib/fog/proxmox/identity.rb
|
|
325
315
|
- lib/fog/proxmox/identity/models/domain.rb
|
|
326
316
|
- lib/fog/proxmox/identity/models/domain_type.rb
|
|
@@ -422,12 +412,15 @@ files:
|
|
|
422
412
|
- spec/fog/proxmox/storage/real_upload_iso_spec.rb
|
|
423
413
|
- spec/fog/proxmox/storage/storage_upload_iso_spec.rb
|
|
424
414
|
- spec/hash_spec.rb
|
|
415
|
+
- spec/helpers/agent_helper_spec.rb
|
|
425
416
|
- spec/helpers/controller_helper_spec.rb
|
|
426
417
|
- spec/helpers/cpu_helper_spec.rb
|
|
427
418
|
- spec/helpers/disk_helper_spec.rb
|
|
428
419
|
- spec/helpers/efidisk_helper_spec.rb
|
|
420
|
+
- spec/helpers/hotplug_helper_spec.rb
|
|
429
421
|
- spec/helpers/ip_helper_spec.rb
|
|
430
422
|
- spec/helpers/nic_helper_spec.rb
|
|
423
|
+
- spec/helpers/rng_helper_spec.rb
|
|
431
424
|
- spec/identity_spec.rb
|
|
432
425
|
- spec/network_spec.rb
|
|
433
426
|
- spec/proxmox_vcr.rb
|