fog-proxmox 0.14.0 → 0.15.1
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 +15 -0
- data/README.md +28 -4
- data/lib/fog/proxmox/attributes.rb +3 -2
- data/lib/fog/proxmox/auth/token/access_ticket.rb +68 -57
- data/lib/fog/proxmox/auth/token/user_token.rb +79 -66
- data/lib/fog/proxmox/auth/token.rb +66 -60
- data/lib/fog/proxmox/compute/models/disk.rb +6 -1
- data/lib/fog/proxmox/compute/models/disks.rb +1 -1
- data/lib/fog/proxmox/compute/models/interface.rb +1 -1
- data/lib/fog/proxmox/compute/models/interfaces.rb +1 -1
- data/lib/fog/proxmox/compute/models/node.rb +3 -5
- data/lib/fog/proxmox/compute/models/nodes.rb +1 -1
- data/lib/fog/proxmox/compute/models/server.rb +33 -16
- data/lib/fog/proxmox/compute/models/server_config.rb +9 -4
- data/lib/fog/proxmox/compute/models/servers.rb +5 -5
- data/lib/fog/proxmox/compute/models/snapshot.rb +1 -1
- data/lib/fog/proxmox/compute/models/snapshots.rb +1 -1
- data/lib/fog/proxmox/compute/models/storage.rb +3 -2
- data/lib/fog/proxmox/compute/models/storages.rb +2 -2
- data/lib/fog/proxmox/compute/models/task.rb +1 -1
- data/lib/fog/proxmox/compute/models/tasks.rb +1 -0
- data/lib/fog/proxmox/compute/models/volume.rb +2 -1
- data/lib/fog/proxmox/compute/models/volumes.rb +2 -2
- data/lib/fog/proxmox/compute/requests/get_server_config.rb +14 -14
- data/lib/fog/proxmox/compute/requests/get_server_status.rb +17 -17
- data/lib/fog/proxmox/compute/requests/log_task.rb +1 -1
- data/lib/fog/proxmox/core.rb +28 -24
- data/lib/fog/proxmox/errors.rb +2 -1
- data/lib/fog/proxmox/hash.rb +0 -2
- data/lib/fog/proxmox/helpers/controller_helper.rb +3 -4
- data/lib/fog/proxmox/helpers/cpu_helper.rb +13 -6
- data/lib/fog/proxmox/helpers/disk_helper.rb +18 -12
- data/lib/fog/proxmox/helpers/ip_helper.rb +21 -20
- data/lib/fog/proxmox/helpers/nic_helper.rb +23 -14
- data/lib/fog/proxmox/identity/models/domain.rb +7 -3
- data/lib/fog/proxmox/identity/models/domain_type.rb +0 -1
- data/lib/fog/proxmox/identity/models/domains.rb +1 -2
- data/lib/fog/proxmox/identity/models/group.rb +4 -2
- data/lib/fog/proxmox/identity/models/groups.rb +1 -1
- data/lib/fog/proxmox/identity/models/permission.rb +5 -4
- data/lib/fog/proxmox/identity/models/permissions.rb +3 -1
- data/lib/fog/proxmox/identity/models/pool.rb +4 -4
- data/lib/fog/proxmox/identity/models/pools.rb +4 -4
- data/lib/fog/proxmox/identity/models/role.rb +1 -1
- data/lib/fog/proxmox/identity/models/roles.rb +1 -1
- data/lib/fog/proxmox/identity/models/token.rb +4 -3
- data/lib/fog/proxmox/identity/models/token_info.rb +2 -2
- data/lib/fog/proxmox/identity/models/tokens.rb +9 -13
- data/lib/fog/proxmox/identity/models/user.rb +1 -2
- data/lib/fog/proxmox/identity/models/users.rb +1 -1
- data/lib/fog/proxmox/identity/requests/get_user.rb +1 -0
- data/lib/fog/proxmox/identity/requests/list_user_permissions.rb +1 -1
- data/lib/fog/proxmox/network/models/networks.rb +1 -1
- data/lib/fog/proxmox/network/models/node.rb +1 -0
- data/lib/fog/proxmox/network/models/nodes.rb +1 -1
- data/lib/fog/proxmox/string.rb +4 -3
- data/lib/fog/proxmox/version.rb +1 -1
- data/lib/fog/proxmox.rb +1 -3
- data/spec/compute_spec.rb +3 -2
- data/spec/fixtures/proxmox/compute/snapshots.yml +350 -1055
- data/spec/hash_spec.rb +2 -1
- data/spec/helpers/controller_helper_spec.rb +135 -123
- data/spec/helpers/cpu_helper_spec.rb +58 -53
- data/spec/helpers/disk_helper_spec.rb +104 -54
- data/spec/helpers/ip_helper_spec.rb +155 -138
- data/spec/helpers/nic_helper_spec.rb +29 -20
- data/spec/identity_spec.rb +86 -74
- data/spec/proxmox_vcr.rb +3 -3
- metadata +89 -90
- data/.bundle/config +0 -4
- data/.codeclimate.yml +0 -14
- data/.github/CODE_OF_CONDUCT.md +0 -74
- data/.github/CONTRIBUTING.md +0 -20
- data/.github/CONTRIBUTORS.md +0 -9
- data/.github/FUNDING.yml +0 -12
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -35
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -17
- data/.github/ISSUE_TEMPLATE.md +0 -43
- data/.github/SUPPORT.md +0 -9
- data/.github/fogproxmox.png +0 -0
- data/.github/workflows/ci.yml +0 -79
- data/.gitignore +0 -8
- data/.rubocop.yml +0 -13
- data/.ruby-gemset +0 -1
- data/.solargraph.yml +0 -10
- data/.vscode/launch.json +0 -96
- data/.vscode/settings.json +0 -45
- data/.vscode/tasks.json +0 -27
- data/Gemfile +0 -23
- data/Rakefile +0 -58
- data/bin/console +0 -29
- data/bin/setup +0 -29
- data/fog-proxmox.gemspec +0 -63
@@ -26,6 +26,7 @@ module Fog
|
|
26
26
|
module Proxmox
|
27
27
|
class Compute
|
28
28
|
# Server model
|
29
|
+
# rubocop:disable ClassLength
|
29
30
|
class Server < Fog::Compute::Server
|
30
31
|
identity :vmid
|
31
32
|
attribute :type
|
@@ -72,20 +73,21 @@ module Fog
|
|
72
73
|
super(new_attributes)
|
73
74
|
end
|
74
75
|
|
76
|
+
def to_s
|
77
|
+
name
|
78
|
+
end
|
79
|
+
|
75
80
|
def container?
|
76
81
|
type == 'lxc'
|
77
82
|
end
|
78
83
|
|
79
84
|
def persisted?
|
80
85
|
service.next_vmid(vmid: vmid)
|
81
|
-
|
82
|
-
persisted
|
86
|
+
false
|
83
87
|
rescue Excon::Error::InternalServerError
|
84
|
-
|
85
|
-
persisted
|
88
|
+
false
|
86
89
|
rescue Excon::Error::BadRequest
|
87
|
-
|
88
|
-
persisted
|
90
|
+
true
|
89
91
|
end
|
90
92
|
|
91
93
|
# request with async task
|
@@ -122,6 +124,7 @@ module Fog
|
|
122
124
|
action_known = %w[start stop resume suspend shutdown reset].include? action
|
123
125
|
message = "Action #{action} not implemented"
|
124
126
|
raise Fog::Errors::Error, message unless action_known
|
127
|
+
|
125
128
|
request(:action_server, options, action: action, vmid: vmid)
|
126
129
|
reload
|
127
130
|
end
|
@@ -136,11 +139,11 @@ module Fog
|
|
136
139
|
end
|
137
140
|
|
138
141
|
def restore(backup, options = {})
|
139
|
-
if container?
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
142
|
+
attr_hash = if container?
|
143
|
+
options.merge(ostemplate: backup.volid, force: 1, restore: 1)
|
144
|
+
else
|
145
|
+
options.merge(archive: backup.volid, force: 1)
|
146
|
+
end
|
144
147
|
save(attr_hash)
|
145
148
|
end
|
146
149
|
|
@@ -186,14 +189,24 @@ module Fog
|
|
186
189
|
end
|
187
190
|
|
188
191
|
def start_console(options = {})
|
189
|
-
|
192
|
+
unless ready?
|
193
|
+
raise ::Fog::Proxmox::Errors::ServiceError,
|
194
|
+
'Unable to start console because server not running.'
|
195
|
+
end
|
196
|
+
|
190
197
|
if container?
|
191
198
|
type_console = options[:console]
|
192
199
|
options.delete_if { |option| [:console].include? option }
|
193
|
-
|
200
|
+
unless type_console
|
201
|
+
raise ::Fog::Proxmox::Errors::ServiceError,
|
202
|
+
'Unable to start console because console container config is not set or unknown.'
|
203
|
+
end
|
194
204
|
else
|
195
205
|
type_console = config.type_console
|
196
|
-
|
206
|
+
unless type_console
|
207
|
+
raise ::Fog::Proxmox::Errors::ServiceError,
|
208
|
+
'Unable to start console because VGA display server config is not set or unknown.'
|
209
|
+
end
|
197
210
|
end
|
198
211
|
requires :vmid, :node_id, :type
|
199
212
|
path_params = { node: node_id, type: type, vmid: vmid }
|
@@ -238,17 +251,21 @@ module Fog
|
|
238
251
|
private
|
239
252
|
|
240
253
|
def initialize_snapshots
|
241
|
-
attributes[:snapshots] =
|
254
|
+
attributes[:snapshots] =
|
255
|
+
Fog::Proxmox::Compute::Snapshots.new(service: service, server_id: vmid, server_type: type, node_id: node_id)
|
242
256
|
end
|
243
257
|
|
244
258
|
def initialize_tasks
|
245
|
-
attributes[:tasks] = Fog::Proxmox::Compute::Tasks.new(service: service, node_id: node_id).select
|
259
|
+
attributes[:tasks] = Fog::Proxmox::Compute::Tasks.new(service: service, node_id: node_id).select do |task|
|
260
|
+
task.id == vmid
|
261
|
+
end
|
246
262
|
end
|
247
263
|
|
248
264
|
def node
|
249
265
|
Fog::Proxmox::Compute::Node.new(service: service, node: node_id)
|
250
266
|
end
|
251
267
|
end
|
268
|
+
# rubocop:enable ClassLength
|
252
269
|
end
|
253
270
|
end
|
254
271
|
end
|
@@ -24,7 +24,8 @@ require 'fog/proxmox/helpers/controller_helper'
|
|
24
24
|
module Fog
|
25
25
|
module Proxmox
|
26
26
|
class Compute
|
27
|
-
# ServerConfig model
|
27
|
+
# ServerConfig model: https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}/{qemu|lxc}/{vmid}/config
|
28
|
+
# memory, balloon, shares and swap are in Mb
|
28
29
|
class ServerConfig < Fog::Model
|
29
30
|
identity :vmid
|
30
31
|
attribute :description
|
@@ -99,7 +100,7 @@ module Fog
|
|
99
100
|
end
|
100
101
|
|
101
102
|
def flatten
|
102
|
-
flat_hash = attributes.reject { |attribute| [
|
103
|
+
flat_hash = attributes.reject { |attribute| %i[node_id type vmid disks interfaces].include? attribute }
|
103
104
|
flat_hash.merge(interfaces_flatten)
|
104
105
|
flat_hash.merge(disks_flatten)
|
105
106
|
flat_hash
|
@@ -128,7 +129,9 @@ module Fog
|
|
128
129
|
model: Fog::Proxmox::NicHelper.extract_nic_id(value),
|
129
130
|
macaddr: Fog::Proxmox::NicHelper.extract_mac_address(value)
|
130
131
|
}
|
131
|
-
names = Fog::Proxmox::Compute::Interface.attributes.reject
|
132
|
+
names = Fog::Proxmox::Compute::Interface.attributes.reject do |attribute|
|
133
|
+
%i[id macaddr model].include? attribute
|
134
|
+
end
|
132
135
|
names.each { |name| nic_hash.store(name.to_sym, Fog::Proxmox::ControllerHelper.extract(name, value)) }
|
133
136
|
attributes[:interfaces] << Fog::Proxmox::Compute::Interface.new(nic_hash)
|
134
137
|
end
|
@@ -145,7 +148,9 @@ module Fog
|
|
145
148
|
volid: volid,
|
146
149
|
storage: storage
|
147
150
|
}
|
148
|
-
names = Fog::Proxmox::Compute::Disk.attributes.reject
|
151
|
+
names = Fog::Proxmox::Compute::Disk.attributes.reject do |attribute|
|
152
|
+
%i[id size storage volid].include? attribute
|
153
|
+
end
|
149
154
|
names.each { |name| disk_hash.store(name.to_sym, Fog::Proxmox::ControllerHelper.extract(name, value)) }
|
150
155
|
attributes[:disks] << Fog::Proxmox::Compute::Disk.new(disk_hash)
|
151
156
|
end
|
@@ -52,12 +52,12 @@ module Fog
|
|
52
52
|
begin
|
53
53
|
status_data = service.get_server_status path_params
|
54
54
|
config_data = service.get_server_config path_params
|
55
|
-
rescue => e
|
55
|
+
rescue StandardError => e
|
56
56
|
if e.respond_to?('response') && e.response.respond_to?('data') && e.response.data.has_key?(:reason_phrase) && e.response.data[:reason_phrase].end_with?('does not exist')
|
57
57
|
raise(Fog::Errors::NotFound)
|
58
|
-
else
|
59
|
-
raise(e)
|
60
58
|
end
|
59
|
+
|
60
|
+
raise(e)
|
61
61
|
else
|
62
62
|
data = status_data.merge(config_data).merge(node: node_id, vmid: id)
|
63
63
|
new(data)
|
@@ -70,8 +70,8 @@ module Fog
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def create(new_attributes = {})
|
73
|
-
object = new(new_attributes.select { |key, _value| [
|
74
|
-
object.save(new_attributes.reject { |key, _value| [
|
73
|
+
object = new(new_attributes.select { |key, _value| %i[node_id vmid type].include? key.to_sym })
|
74
|
+
object.save(new_attributes.reject { |key, _value| %i[node_id vmid type].include? key.to_sym })
|
75
75
|
object
|
76
76
|
end
|
77
77
|
end
|
@@ -51,7 +51,7 @@ module Fog
|
|
51
51
|
|
52
52
|
def save
|
53
53
|
path_params = { node: node_id, type: server_type, vmid: server_id }
|
54
|
-
body_params = { snapname: name }
|
54
|
+
body_params = { snapname: name, vmstate: vmstate }
|
55
55
|
server.tasks.wait_for(service.create_snapshot(path_params, body_params))
|
56
56
|
end
|
57
57
|
|
@@ -29,7 +29,7 @@
|
|
29
29
|
module Fog
|
30
30
|
module Proxmox
|
31
31
|
class Compute
|
32
|
-
# class Storage model
|
32
|
+
# class Storage model: https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}/storage/{storage}
|
33
33
|
class Storage < Fog::Model
|
34
34
|
identity :storage
|
35
35
|
attribute :node_id, aliases: :node
|
@@ -56,7 +56,8 @@ module Fog
|
|
56
56
|
private
|
57
57
|
|
58
58
|
def initialize_volumes
|
59
|
-
attributes[:volumes] =
|
59
|
+
attributes[:volumes] =
|
60
|
+
Fog::Proxmox::Compute::Volumes.new(service: service, node_id: node_id, storage_id: identity)
|
60
61
|
end
|
61
62
|
end
|
62
63
|
end
|
@@ -26,7 +26,7 @@ module Fog
|
|
26
26
|
class Storages < Fog::Collection
|
27
27
|
model Fog::Proxmox::Compute::Storage
|
28
28
|
attribute :node_id
|
29
|
-
|
29
|
+
|
30
30
|
def new(new_attributes = {})
|
31
31
|
super({ node_id: node_id }.merge(new_attributes))
|
32
32
|
end
|
@@ -43,7 +43,7 @@ module Fog
|
|
43
43
|
|
44
44
|
def get(id)
|
45
45
|
requires :node_id
|
46
|
-
all.find { |storage| storage.identity
|
46
|
+
all.find { |storage| storage.identity == id }
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
@@ -31,7 +31,8 @@ require 'fog/proxmox/helpers/disk_helper'
|
|
31
31
|
module Fog
|
32
32
|
module Proxmox
|
33
33
|
class Compute
|
34
|
-
# class Volume model
|
34
|
+
# class Volume model: https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}/storage/{storage}/content/{volume}
|
35
|
+
# size is in bytes
|
35
36
|
class Volume < Fog::Model
|
36
37
|
identity :volid
|
37
38
|
attribute :content
|
@@ -37,10 +37,10 @@ module Fog
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def list_by_content_type(content)
|
40
|
-
all.select { |volume| volume.content.include? content}
|
40
|
+
all.select { |volume| volume.content.include? content }
|
41
41
|
end
|
42
42
|
|
43
|
-
def list_by_content_type_and_by_server(
|
43
|
+
def list_by_content_type_and_by_server(_content, vmid)
|
44
44
|
all(vmid: vmid)
|
45
45
|
end
|
46
46
|
|
@@ -38,20 +38,20 @@ module Fog
|
|
38
38
|
class Mock
|
39
39
|
def get_server_config(_path_params)
|
40
40
|
{
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
47
|
-
:
|
48
|
-
:
|
49
|
-
:
|
50
|
-
:
|
51
|
-
:
|
52
|
-
:
|
53
|
-
:
|
54
|
-
:
|
41
|
+
onboot: 0,
|
42
|
+
memory: 512,
|
43
|
+
ostype: 'l26',
|
44
|
+
cores: 1,
|
45
|
+
keyboard: 'en-us',
|
46
|
+
digest: nil,
|
47
|
+
smbios1: nil,
|
48
|
+
vmgenid: nil,
|
49
|
+
balloon: 0,
|
50
|
+
kvm: 0,
|
51
|
+
cpu: 'cputype=kvm64',
|
52
|
+
sockets: 1,
|
53
|
+
bootdisk: 'scsi0',
|
54
|
+
vga: 'std'
|
55
55
|
}
|
56
56
|
end
|
57
57
|
end
|
@@ -38,23 +38,23 @@ module Fog
|
|
38
38
|
class Mock
|
39
39
|
def get_server_status(_path_params)
|
40
40
|
{
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
47
|
-
:
|
48
|
-
:
|
49
|
-
:
|
50
|
-
:
|
51
|
-
:
|
52
|
-
:
|
53
|
-
:
|
54
|
-
:
|
55
|
-
:
|
56
|
-
:
|
57
|
-
:
|
41
|
+
netout: 0,
|
42
|
+
ha: { 'managed' => 0 },
|
43
|
+
mem: 0,
|
44
|
+
vmid: '100',
|
45
|
+
maxdisk: 8_589_934_592,
|
46
|
+
diskread: 0,
|
47
|
+
template: '',
|
48
|
+
qmpstatus: 'stopped',
|
49
|
+
diskwrite: 0,
|
50
|
+
maxmem: 536_870_912,
|
51
|
+
pid: nil,
|
52
|
+
uptime: 0,
|
53
|
+
status: 'stopped',
|
54
|
+
cpu: 'cputype=kvm64',
|
55
|
+
cpus: 1,
|
56
|
+
disk: 0,
|
57
|
+
netin: 0
|
58
58
|
}
|
59
59
|
end
|
60
60
|
end
|
data/lib/fog/proxmox/core.rb
CHANGED
@@ -26,9 +26,7 @@ module Fog
|
|
26
26
|
# Core module
|
27
27
|
module Core
|
28
28
|
attr_accessor :token
|
29
|
-
attr_reader :auth_method
|
30
|
-
attr_reader :expires
|
31
|
-
attr_reader :current_user
|
29
|
+
attr_reader :auth_method, :expires, :current_user
|
32
30
|
|
33
31
|
def user_token?
|
34
32
|
@auth_token == 'user_token'
|
@@ -46,24 +44,25 @@ module Fog
|
|
46
44
|
@connection = Fog::Core::Connection.new(@proxmox_url, @persistent, @connection_options)
|
47
45
|
end
|
48
46
|
|
49
|
-
def setup(options)
|
47
|
+
def setup(options)
|
50
48
|
if options.respond_to?(:config_service?) && options.config_service?
|
51
49
|
configure(options)
|
52
50
|
return
|
53
51
|
end
|
54
52
|
Fog::Proxmox::Variables.to_variables(self, options, 'proxmox')
|
55
53
|
@connection_options = options[:connection_options] || {}
|
56
|
-
@connection_options[:disable_proxy] = true if ENV['DISABLE_PROXY'] == 'true'
|
54
|
+
@connection_options[:disable_proxy] = true if ENV['DISABLE_PROXY'] == 'true'
|
57
55
|
@connection_options[:ssl_verify_peer] = false if ENV['SSL_VERIFY_PEER'] == 'false'
|
56
|
+
@connection_options[:ignore_unexpected_eof] = true
|
58
57
|
@proxmox_must_reauthenticate = true
|
59
|
-
@persistent = options[:persistent] || false
|
60
|
-
@token ||= options[:proxmox_token]
|
61
|
-
@auth_method ||= options[:proxmox_auth_method]
|
62
|
-
if @token
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
58
|
+
@persistent = options[:persistent] || false
|
59
|
+
@token ||= options[:proxmox_token]
|
60
|
+
@auth_method ||= options[:proxmox_auth_method]
|
61
|
+
@proxmox_can_reauthenticate = if @token
|
62
|
+
false
|
63
|
+
else
|
64
|
+
true
|
65
|
+
end
|
67
66
|
end
|
68
67
|
|
69
68
|
def credentials
|
@@ -85,31 +84,36 @@ module Fog
|
|
85
84
|
def expired?
|
86
85
|
return false if @expires.nil?
|
87
86
|
return false if @expires == 0
|
88
|
-
|
87
|
+
|
88
|
+
@expires - Time.now.utc.to_i < 60
|
89
89
|
end
|
90
90
|
|
91
91
|
def request(params)
|
92
|
-
retried = false
|
92
|
+
retried = false
|
93
93
|
begin
|
94
94
|
authenticate! if expired?
|
95
|
-
request_options = params.merge(path: "#{@path}/#{params[:path]}",
|
95
|
+
request_options = params.merge(path: "#{@path}/#{params[:path]}",
|
96
|
+
headers: @auth_token.headers(
|
97
|
+
params[:method], params.respond_to?(:headers) ? params[:headers] : {}, {}
|
98
|
+
))
|
96
99
|
response = @connection.request(request_options)
|
97
|
-
rescue Excon::Errors::Unauthorized =>
|
100
|
+
rescue Excon::Errors::Unauthorized => e
|
98
101
|
# token expiration and token renewal possible
|
99
|
-
if !%w[Bad username or password, invalid token
|
102
|
+
if !%w[Bad username or password, invalid token
|
103
|
+
value!].include?(e.response.body) && @proxmox_can_reauthenticate && !retried
|
100
104
|
authenticate!
|
101
105
|
retried = true
|
102
106
|
retry
|
103
107
|
# bad credentials or token renewal not possible
|
104
108
|
else
|
105
|
-
raise
|
109
|
+
raise e
|
106
110
|
end
|
107
|
-
rescue Excon::Errors::HTTPStatusError =>
|
108
|
-
raise case
|
111
|
+
rescue Excon::Errors::HTTPStatusError => e
|
112
|
+
raise case e
|
109
113
|
when Excon::Errors::NotFound
|
110
|
-
self.class.not_found_class.slurp(
|
114
|
+
self.class.not_found_class.slurp(e)
|
111
115
|
else
|
112
|
-
|
116
|
+
e
|
113
117
|
end
|
114
118
|
end
|
115
119
|
Fog::Proxmox::Json.get_data(response)
|
@@ -123,7 +127,7 @@ module Fog
|
|
123
127
|
if @proxmox_must_reauthenticate
|
124
128
|
@token = nil if @proxmox_must_reauthenticate
|
125
129
|
@auth_token = Fog::Proxmox::Auth::Token.build(proxmox_options, @connection_options)
|
126
|
-
@current_user = proxmox_options[:proxmox_userid]
|
130
|
+
@current_user = proxmox_options[:proxmox_userid] || proxmox_options[:proxmox_username]
|
127
131
|
@token = @auth_token.token
|
128
132
|
@expires = @auth_token.expires
|
129
133
|
@proxmox_must_reauthenticate = false
|
data/lib/fog/proxmox/errors.rb
CHANGED
@@ -51,7 +51,8 @@ module Fog
|
|
51
51
|
def self.slurp(error)
|
52
52
|
new_error = super(error)
|
53
53
|
unless new_error.response_data.nil? || new_error.response_data['badRequest'].nil?
|
54
|
-
new_error.instance_variable_set(:@validation_errors,
|
54
|
+
new_error.instance_variable_set(:@validation_errors,
|
55
|
+
new_error.response_data['badRequest']['validationErrors'])
|
55
56
|
end
|
56
57
|
new_error
|
57
58
|
end
|
data/lib/fog/proxmox/hash.rb
CHANGED
@@ -21,7 +21,6 @@ module Fog
|
|
21
21
|
module Proxmox
|
22
22
|
# module Hash mixins
|
23
23
|
module Hash
|
24
|
-
|
25
24
|
def self.stringify(hash)
|
26
25
|
filtered = hash.reject { |_key, value| value.nil? }
|
27
26
|
a = filtered.to_a.collect { |item| item.join('=') }
|
@@ -33,7 +32,6 @@ module Fog
|
|
33
32
|
a = filtered.to_a.collect { |item| item.join(': ') }
|
34
33
|
a.join(',')
|
35
34
|
end
|
36
|
-
|
37
35
|
end
|
38
36
|
end
|
39
37
|
end
|
@@ -21,10 +21,9 @@ module Fog
|
|
21
21
|
module Proxmox
|
22
22
|
# module ControllerHelper mixins
|
23
23
|
module ControllerHelper
|
24
|
-
|
25
24
|
CONTROLLERS = %w[ide sata scsi virtio mp rootfs].freeze
|
26
25
|
def self.extract(name, controller_value)
|
27
|
-
matches = controller_value.match(
|
26
|
+
matches = controller_value.match(%r{,{0,1}#{name}={1}(?<name_value>[\w/.:]+)})
|
28
27
|
matches ? matches[:name_value] : matches
|
29
28
|
end
|
30
29
|
|
@@ -40,6 +39,7 @@ module Fog
|
|
40
39
|
|
41
40
|
def self.last_index(name, values)
|
42
41
|
return -1 if values.empty?
|
42
|
+
|
43
43
|
indexes = []
|
44
44
|
values.each do |value|
|
45
45
|
index = extract_index(name, value)
|
@@ -49,7 +49,7 @@ module Fog
|
|
49
49
|
indexes.empty? ? -1 : indexes.last
|
50
50
|
end
|
51
51
|
|
52
|
-
def self.select(hash,name)
|
52
|
+
def self.select(hash, name)
|
53
53
|
hash.select { |key| valid?(name, key.to_s) }
|
54
54
|
end
|
55
55
|
|
@@ -58,7 +58,6 @@ module Fog
|
|
58
58
|
CONTROLLERS.each { |controller| controllers.merge!(select(attributes, controller)) }
|
59
59
|
controllers
|
60
60
|
end
|
61
|
-
|
62
61
|
end
|
63
62
|
end
|
64
63
|
end
|
@@ -21,12 +21,13 @@ module Fog
|
|
21
21
|
module Proxmox
|
22
22
|
# module Cpu mixins
|
23
23
|
module CpuHelper
|
24
|
-
CPU_REGEXP = /(\bcputype=)?(?<cputype>[\w-]+)
|
25
|
-
FLAGS = { spectre: 'spec-ctrl', pcid: 'pcid', ssbd: 'ssbd', ibpb: 'ibpb', virt_ssbd: 'virt-ssbd',
|
24
|
+
CPU_REGEXP = /(\bcputype=)?(?<cputype>[\w-]+),?(\bflags=)?(?<flags>[[+-][\w-]+;?]*)/
|
25
|
+
FLAGS = { spectre: 'spec-ctrl', pcid: 'pcid', ssbd: 'ssbd', ibpb: 'ibpb', virt_ssbd: 'virt-ssbd',
|
26
|
+
amd_ssbd: 'amd-ssbd', amd_no_ssb: 'amd-no-ssb', md_clear: 'md-clear', pdpe1gb: 'pdpe1gb', hv_tlbflush: 'hv-tlbflush', aes: 'aes', hv_evmcs: 'hv-evmcs' }
|
26
27
|
def self.flags
|
27
28
|
FLAGS
|
28
29
|
end
|
29
|
-
|
30
|
+
|
30
31
|
def self.extract(cpu, name)
|
31
32
|
captures_h = cpu ? CPU_REGEXP.match(cpu.to_s) : { cputype: '', flags: '' }
|
32
33
|
captures_h[name]
|
@@ -44,7 +45,11 @@ module Fog
|
|
44
45
|
flag_value = '0'
|
45
46
|
raw_values = extract_flags(cpu).split(';').select { |flag| ['+' + flag_key, '-' + flag_key].include?(flag) }
|
46
47
|
unless raw_values.empty?
|
47
|
-
flag_value = raw_values[0].start_with?('+')
|
48
|
+
flag_value = if raw_values[0].start_with?('+')
|
49
|
+
'+1'
|
50
|
+
else
|
51
|
+
raw_values[0].start_with?('-') ? '-1' : '0'
|
52
|
+
end
|
48
53
|
end
|
49
54
|
flag_value
|
50
55
|
end
|
@@ -64,12 +69,14 @@ module Fog
|
|
64
69
|
|
65
70
|
def self.flatten(cpu_h)
|
66
71
|
return '' unless cpu_h['cpu_type']
|
67
|
-
|
72
|
+
|
68
73
|
cpu_type = "cputype=#{cpu_h['cpu_type']}"
|
69
74
|
num_flags = 0
|
70
75
|
FLAGS.each_key { |flag_key| num_flags += 1 if hash_has_no_default_flag?(cpu_h, flag_key.to_s) }
|
71
76
|
cpu_type += ',flags=' if num_flags > 0
|
72
|
-
flags_with_no_default_value = FLAGS.select
|
77
|
+
flags_with_no_default_value = FLAGS.select do |flag_key, _flag_value|
|
78
|
+
hash_has_no_default_flag?(cpu_h, flag_key.to_s)
|
79
|
+
end
|
73
80
|
flags_with_no_default_value.each_with_index do |(flag_key, flag_value), index|
|
74
81
|
cpu_type += hash_flag(cpu_h, flag_key.to_s) + flag_value if hash_has_no_default_flag?(cpu_h, flag_key.to_s)
|
75
82
|
cpu_type += ';' if num_flags > index + 1
|
@@ -27,7 +27,7 @@ module Fog
|
|
27
27
|
SERVER_DISK_REGEXP = /^(scsi|sata|virtio|ide)(\d+)$/
|
28
28
|
MOUNT_POINT_REGEXP = /^(mp)(\d+)$/
|
29
29
|
ROOTFS_REGEXP = /^(rootfs)$/
|
30
|
-
CDROM_REGEXP = /^(.*)
|
30
|
+
CDROM_REGEXP = /^(.*),{0,1}(media=cdrom),{0,1}(.*)$/
|
31
31
|
TEMPLATE_REGEXP = /^(.*)(base-)(.*)$/
|
32
32
|
CLOUD_INIT_REGEXP = /^(.*)(cloudinit)(.*)$/
|
33
33
|
|
@@ -44,7 +44,7 @@ module Fog
|
|
44
44
|
value += 'none'
|
45
45
|
end
|
46
46
|
opts = disk[:options] if disk[:options]
|
47
|
-
main_a = [
|
47
|
+
main_a = %i[id volid storage size]
|
48
48
|
opts ||= disk.reject { |key, _value| main_a.include? key }
|
49
49
|
options = ''
|
50
50
|
options += Fog::Proxmox::Hash.stringify(opts) if opts
|
@@ -79,9 +79,9 @@ module Fog
|
|
79
79
|
# Convert API Proxmox volume/disk parameter string into volume/disk attributes hash value
|
80
80
|
def self.extract_storage_volid_size(disk_value)
|
81
81
|
# volid definition: <VOLUME_ID>:=<STORAGE_ID>:<storage type dependent volume name>
|
82
|
-
values_a = disk_value.scan(
|
82
|
+
values_a = disk_value.scan(%r{^(([\w-]+):{0,1}([\w/.-]+))})
|
83
83
|
no_cdrom = !disk_value.match(CDROM_REGEXP)
|
84
|
-
creation = disk_value.split(',')[0].match(/^(([\w-]+)
|
84
|
+
creation = disk_value.split(',')[0].match(/^(([\w-]+):{1}(\d+))$/)
|
85
85
|
values = values_a.first if values_a
|
86
86
|
if no_cdrom
|
87
87
|
storage = values[1]
|
@@ -104,11 +104,11 @@ module Fog
|
|
104
104
|
val = size.match(/\d+(\w?)/)
|
105
105
|
m = 0
|
106
106
|
case val[1]
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
107
|
+
when 'K' then m = 1
|
108
|
+
when 'M' then m = 2
|
109
|
+
when 'G' then m = 3
|
110
|
+
when 'T' then m = 4
|
111
|
+
when 'P' then m = 5
|
112
112
|
end
|
113
113
|
val[0].to_i * 1024**m
|
114
114
|
end
|
@@ -118,10 +118,10 @@ module Fog
|
|
118
118
|
end
|
119
119
|
|
120
120
|
def self.to_human_bytes(size)
|
121
|
-
units = [
|
121
|
+
units = %w[Kb Mb Gb]
|
122
122
|
i = 0
|
123
123
|
human_size = size.to_s + 'b'
|
124
|
-
while i <
|
124
|
+
while i < 3 && size >= 1024
|
125
125
|
size = modulo_bytes(size)
|
126
126
|
human_size = size.to_s + units[i]
|
127
127
|
i += 1
|
@@ -129,9 +129,15 @@ module Fog
|
|
129
129
|
human_size
|
130
130
|
end
|
131
131
|
|
132
|
+
def self.to_int_gb(size_bytes)
|
133
|
+
val = to_human_bytes(size_bytes.to_i).match(/\d+(Gb)/)
|
134
|
+
val ? val[0].to_i : 0
|
135
|
+
end
|
136
|
+
|
132
137
|
def self.extract_size(disk_value)
|
133
138
|
size = extract_option('size', disk_value)
|
134
|
-
size
|
139
|
+
size = to_int_gb(to_bytes(size)).to_s if size.match?(/\d+(G)/)
|
140
|
+
size
|
135
141
|
end
|
136
142
|
|
137
143
|
def self.disk?(id)
|