fog-proxmox 0.13.0 → 0.14.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.
Files changed (174) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -1
  3. data/docs/compute.md +23 -7
  4. data/docs/identity.md +31 -6
  5. data/examples/compute.rb +11 -11
  6. data/examples/identity.rb +28 -15
  7. data/fog-proxmox.gemspec +1 -1
  8. data/lib/fog/proxmox.rb +16 -76
  9. data/lib/fog/proxmox/auth/token.rb +88 -0
  10. data/lib/fog/proxmox/auth/token/access_ticket.rb +85 -0
  11. data/lib/fog/proxmox/auth/token/user_token.rb +94 -0
  12. data/lib/fog/{compute/proxmox.rb → proxmox/compute.rb} +31 -16
  13. data/lib/fog/{compute/proxmox → proxmox/compute}/models/disk.rb +15 -2
  14. data/lib/fog/{compute/proxmox → proxmox/compute}/models/disks.rb +5 -1
  15. data/lib/fog/{compute/proxmox → proxmox/compute}/models/interface.rb +4 -0
  16. data/lib/fog/{compute/proxmox → proxmox/compute}/models/interfaces.rb +1 -1
  17. data/lib/fog/{compute/proxmox → proxmox/compute}/models/node.rb +0 -0
  18. data/lib/fog/{compute/proxmox → proxmox/compute}/models/nodes.rb +1 -1
  19. data/lib/fog/{compute/proxmox → proxmox/compute}/models/server.rb +2 -2
  20. data/lib/fog/{compute/proxmox → proxmox/compute}/models/server_config.rb +8 -0
  21. data/lib/fog/{compute/proxmox → proxmox/compute}/models/servers.rb +1 -1
  22. data/lib/fog/{compute/proxmox → proxmox/compute}/models/snapshot.rb +0 -0
  23. data/lib/fog/{compute/proxmox → proxmox/compute}/models/snapshots.rb +1 -1
  24. data/lib/fog/{compute/proxmox → proxmox/compute}/models/storage.rb +0 -0
  25. data/lib/fog/{compute/proxmox → proxmox/compute}/models/storages.rb +1 -1
  26. data/lib/fog/{compute/proxmox → proxmox/compute}/models/task.rb +0 -0
  27. data/lib/fog/{compute/proxmox → proxmox/compute}/models/tasks.rb +1 -1
  28. data/lib/fog/{compute/proxmox → proxmox/compute}/models/volume.rb +6 -0
  29. data/lib/fog/{compute/proxmox → proxmox/compute}/models/volumes.rb +1 -1
  30. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/action_server.rb +0 -0
  31. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/clone_server.rb +0 -0
  32. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/create_backup.rb +0 -0
  33. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/create_server.rb +0 -0
  34. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/create_snapshot.rb +0 -0
  35. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/create_spice.rb +0 -0
  36. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/create_term.rb +0 -0
  37. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/create_vnc.rb +0 -0
  38. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/delete_server.rb +0 -0
  39. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/delete_snapshot.rb +0 -0
  40. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/delete_volume.rb +0 -0
  41. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/get_node_statistics.rb +0 -0
  42. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/get_server_config.rb +0 -0
  43. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/get_server_status.rb +0 -0
  44. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/get_snapshot_config.rb +0 -0
  45. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/get_task.rb +0 -0
  46. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/get_vnc.rb +0 -0
  47. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/get_volume.rb +0 -0
  48. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/list_nodes.rb +0 -0
  49. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/list_servers.rb +0 -0
  50. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/list_snapshots.rb +0 -0
  51. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/list_storages.rb +0 -0
  52. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/list_tasks.rb +0 -0
  53. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/list_volumes.rb +0 -0
  54. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/log_task.rb +0 -0
  55. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/migrate_server.rb +0 -0
  56. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/move_disk.rb +0 -0
  57. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/move_volume.rb +0 -0
  58. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/next_vmid.rb +0 -0
  59. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/resize_container.rb +0 -0
  60. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/resize_server.rb +0 -0
  61. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/rollback_snapshot.rb +0 -0
  62. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/status_task.rb +0 -0
  63. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/stop_task.rb +0 -0
  64. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/template_server.rb +0 -0
  65. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/update_server.rb +0 -0
  66. data/lib/fog/{compute/proxmox → proxmox/compute}/requests/update_snapshot.rb +0 -0
  67. data/lib/fog/proxmox/core.rb +66 -57
  68. data/lib/fog/proxmox/hash.rb +2 -2
  69. data/lib/fog/proxmox/helpers/cpu_helper.rb +48 -9
  70. data/lib/fog/proxmox/helpers/disk_helper.rb +42 -22
  71. data/lib/fog/proxmox/helpers/nic_helper.rb +28 -20
  72. data/lib/fog/{identity/proxmox.rb → proxmox/identity.rb} +31 -17
  73. data/lib/fog/{identity/proxmox → proxmox/identity}/models/domain.rb +0 -0
  74. data/lib/fog/{identity/proxmox → proxmox/identity}/models/domain_type.rb +0 -0
  75. data/lib/fog/{identity/proxmox → proxmox/identity}/models/domains.rb +1 -1
  76. data/lib/fog/{identity/proxmox → proxmox/identity}/models/group.rb +4 -2
  77. data/lib/fog/{identity/proxmox → proxmox/identity}/models/groups.rb +1 -1
  78. data/lib/fog/{identity/proxmox → proxmox/identity}/models/permission.rb +0 -0
  79. data/lib/fog/{identity/proxmox → proxmox/identity}/models/permissions.rb +1 -1
  80. data/lib/fog/{identity/proxmox → proxmox/identity}/models/pool.rb +0 -0
  81. data/lib/fog/{identity/proxmox → proxmox/identity}/models/pools.rb +1 -1
  82. data/lib/fog/{identity/proxmox → proxmox/identity}/models/principal.rb +0 -0
  83. data/lib/fog/{identity/proxmox → proxmox/identity}/models/role.rb +0 -0
  84. data/lib/fog/{identity/proxmox → proxmox/identity}/models/roles.rb +1 -1
  85. data/lib/fog/proxmox/identity/models/token.rb +71 -0
  86. data/lib/fog/proxmox/identity/models/token_info.rb +41 -0
  87. data/lib/fog/proxmox/identity/models/tokens.rb +58 -0
  88. data/lib/fog/{identity/proxmox → proxmox/identity}/models/user.rb +25 -2
  89. data/lib/fog/{identity/proxmox → proxmox/identity}/models/users.rb +1 -1
  90. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/change_password.rb +0 -0
  91. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/check_permissions.rb +0 -0
  92. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/create_domain.rb +0 -0
  93. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/create_group.rb +0 -0
  94. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/create_pool.rb +0 -0
  95. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/create_role.rb +0 -0
  96. data/lib/fog/proxmox/identity/requests/create_token.rb +40 -0
  97. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/create_user.rb +0 -0
  98. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/delete_domain.rb +0 -0
  99. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/delete_group.rb +0 -0
  100. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/delete_pool.rb +0 -0
  101. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/delete_role.rb +0 -0
  102. data/lib/fog/proxmox/identity/requests/delete_token.rb +40 -0
  103. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/delete_user.rb +0 -0
  104. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/get_domain.rb +0 -0
  105. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/get_group.rb +0 -0
  106. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/get_pool.rb +0 -0
  107. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/get_role.rb +0 -0
  108. data/lib/fog/proxmox/identity/requests/get_token_info.rb +41 -0
  109. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/get_user.rb +0 -0
  110. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/list_domains.rb +0 -0
  111. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/list_groups.rb +0 -0
  112. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/list_permissions.rb +0 -0
  113. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/list_pools.rb +0 -0
  114. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/list_roles.rb +0 -0
  115. data/lib/fog/proxmox/identity/requests/list_tokens.rb +41 -0
  116. data/lib/fog/proxmox/identity/requests/list_user_permissions.rb +44 -0
  117. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/list_users.rb +0 -0
  118. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/read_version.rb +0 -0
  119. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/update_domain.rb +0 -0
  120. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/update_group.rb +0 -0
  121. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/update_permissions.rb +0 -0
  122. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/update_pool.rb +0 -0
  123. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/update_role.rb +0 -0
  124. data/lib/fog/proxmox/identity/requests/update_token.rb +41 -0
  125. data/lib/fog/{identity/proxmox → proxmox/identity}/requests/update_user.rb +0 -0
  126. data/lib/fog/{network/proxmox.rb → proxmox/network.rb} +21 -14
  127. data/lib/fog/{network/proxmox → proxmox/network}/models/network.rb +0 -0
  128. data/lib/fog/{network/proxmox → proxmox/network}/models/networks.rb +1 -1
  129. data/lib/fog/{network/proxmox → proxmox/network}/models/node.rb +1 -1
  130. data/lib/fog/{network/proxmox → proxmox/network}/models/nodes.rb +1 -1
  131. data/lib/fog/{network/proxmox → proxmox/network}/requests/create_network.rb +0 -0
  132. data/lib/fog/{network/proxmox → proxmox/network}/requests/delete_network.rb +0 -0
  133. data/lib/fog/{network/proxmox → proxmox/network}/requests/get_network.rb +0 -0
  134. data/lib/fog/{network/proxmox → proxmox/network}/requests/get_node.rb +0 -0
  135. data/lib/fog/{network/proxmox → proxmox/network}/requests/list_networks.rb +0 -0
  136. data/lib/fog/{network/proxmox → proxmox/network}/requests/list_nodes.rb +0 -0
  137. data/lib/fog/{network/proxmox → proxmox/network}/requests/power_node.rb +0 -0
  138. data/lib/fog/{network/proxmox → proxmox/network}/requests/update_network.rb +0 -0
  139. data/lib/fog/{storage/proxmox.rb → proxmox/storage.rb} +1 -1
  140. data/lib/fog/proxmox/version.rb +1 -1
  141. data/spec/compute_spec.rb +4 -4
  142. data/spec/fixtures/proxmox/compute/common_auth.yml +40 -0
  143. data/spec/fixtures/proxmox/compute/containers.yml +1752 -7568
  144. data/spec/fixtures/proxmox/compute/nodes.yml +24 -30
  145. data/spec/fixtures/proxmox/compute/servers.yml +5015 -10683
  146. data/spec/fixtures/proxmox/compute/snapshots.yml +479 -1719
  147. data/spec/fixtures/proxmox/compute/storages.yml +32 -40
  148. data/spec/fixtures/proxmox/compute/tasks.yml +118 -338
  149. data/spec/fixtures/proxmox/identity/auth.yml +10 -12
  150. data/spec/fixtures/proxmox/identity/auth_access_ticket.yml +77 -0
  151. data/spec/fixtures/proxmox/identity/auth_user_token.yml +77 -0
  152. data/spec/fixtures/proxmox/identity/common_auth.yml +40 -0
  153. data/spec/fixtures/proxmox/identity/domains.yml +145 -181
  154. data/spec/fixtures/proxmox/identity/groups.yml +72 -90
  155. data/spec/fixtures/proxmox/identity/permissions.yml +297 -189
  156. data/spec/fixtures/proxmox/identity/pools.yml +176 -421
  157. data/spec/fixtures/proxmox/identity/read_version.yml +7 -9
  158. data/spec/fixtures/proxmox/identity/roles.yml +69 -87
  159. data/spec/fixtures/proxmox/identity/tokens.yml +494 -0
  160. data/spec/fixtures/proxmox/identity/users.yml +149 -187
  161. data/spec/fixtures/proxmox/network/common_auth.yml +40 -0
  162. data/spec/fixtures/proxmox/network/networks.yml +99 -96
  163. data/spec/helpers/cpu_helper_spec.rb +27 -20
  164. data/spec/helpers/disk_helper_spec.rb +231 -187
  165. data/spec/helpers/nic_helper_spec.rb +113 -114
  166. data/spec/identity_spec.rb +110 -28
  167. data/spec/network_spec.rb +3 -3
  168. data/spec/proxmox_vcr.rb +24 -22
  169. data/spec/spec_helper.rb +4 -3
  170. metadata +155 -139
  171. data/spec/fixtures/proxmox/compute/identity_ticket.yml +0 -40
  172. data/spec/fixtures/proxmox/identity/identity_ticket.yml +0 -40
  173. data/spec/fixtures/proxmox/identity/renew.yml +0 -40
  174. data/spec/fixtures/proxmox/network/identity_ticket.yml +0 -40
@@ -17,7 +17,7 @@
17
17
  # You should have received a copy of the GNU General Public License
18
18
  # along with Fog::Proxmox. If not, see <http://www.gnu.org/licenses/>.
19
19
 
20
- require 'fog/compute/proxmox/models/volume'
20
+ require 'fog/proxmox/compute/models/volume'
21
21
 
22
22
  module Fog
23
23
  module Proxmox
@@ -25,41 +25,55 @@ module Fog
25
25
  module Proxmox
26
26
  # Core module
27
27
  module Core
28
- attr_accessor :pve_ticket
29
- attr_reader :pve_csrftoken
30
- attr_reader :pve_username
31
- attr_reader :deadline
32
- attr_reader :principal
28
+ attr_accessor :token
29
+ attr_reader :auth_method
30
+ attr_reader :expires
31
+ attr_reader :current_user
32
+
33
+ def user_token?
34
+ @auth_token == 'user_token'
35
+ end
33
36
 
34
37
  # fallback
35
38
  def self.not_found_class
36
- Fog::Proxmox::Compute::NotFound
39
+ Fog::Proxmox::Core::NotFound
37
40
  end
38
41
 
39
- def initialize_identity(options)
40
- @principal = nil
41
- @pve_ticket = nil
42
- Fog::Proxmox::Variables.to_variables(self, options, 'pve')
43
- @pve_uri = URI.parse(@pve_url)
44
- missing_credentials = []
45
- missing_credentials << :pve_username unless @pve_username
42
+ def initialize(options = {})
43
+ setup(options)
44
+ authenticate
45
+ @auth_token.missing_credentials(options)
46
+ @connection = Fog::Core::Connection.new(@proxmox_url, @persistent, @connection_options)
47
+ end
46
48
 
47
- unless @pve_ticket
48
- missing_credentials << :pve_password unless @pve_password
49
+ def setup(options)
50
+ if options.respond_to?(:config_service?) && options.config_service?
51
+ configure(options)
52
+ return
49
53
  end
50
-
51
- raise ArgumentError, "Missing required arguments: #{missing_credentials.join(', ')}" unless missing_credentials.empty?
54
+ Fog::Proxmox::Variables.to_variables(self, options, 'proxmox')
55
+ @connection_options = options[:connection_options] || {}
56
+ @connection_options[:disable_proxy] = true if ENV['DISABLE_PROXY'] == 'true'
57
+ @connection_options[:ssl_verify_peer] = false if ENV['SSL_VERIFY_PEER'] == 'false'
58
+ @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
+ @proxmox_can_reauthenticate = false
64
+ else
65
+ @proxmox_can_reauthenticate = true
66
+ end
52
67
  end
53
68
 
54
69
  def credentials
55
70
  options = {
56
71
  provider: 'proxmox',
57
- pve_url: @pve_uri.to_s,
58
- pve_ticket: @pve_ticket,
59
- pve_csrftoken: @pve_csrftoken,
60
- pve_username: @pve_username
72
+ proxmox_auth_method: @auth_method,
73
+ proxmox_url: @proxmox_uri.to_s,
74
+ current_user: @current_user
61
75
  }
62
- pve_options.merge options
76
+ proxmox_options.merge options
63
77
  end
64
78
 
65
79
  def reload
@@ -68,16 +82,22 @@ module Fog
68
82
 
69
83
  private
70
84
 
85
+ def expired?
86
+ return false if @expires.nil?
87
+ return false if @expires == 0
88
+ return @expires - Time.now.utc.to_i < 60
89
+ end
90
+
71
91
  def request(params)
72
92
  retried = false
73
93
  begin
74
- response = @connection.request(params.merge(
75
- headers: headers(params[:method], params[:headers])
76
- ))
94
+ authenticate! if expired?
95
+ request_options = params.merge(path: "#{@path}/#{params[:path]}", headers: @auth_token.headers(params[:method], params.respond_to?(:headers) ? params[:headers] : {}, {}))
96
+ response = @connection.request(request_options)
77
97
  rescue Excon::Errors::Unauthorized => error
78
98
  # token expiration and token renewal possible
79
- if error.response.body != 'Bad username or password' && !retried
80
- authenticate
99
+ if !%w[Bad username or password, invalid token value!].include?(error.response.body) && @proxmox_can_reauthenticate && !retried
100
+ authenticate!
81
101
  retried = true
82
102
  retry
83
103
  # bad credentials or token renewal not possible
@@ -95,41 +115,30 @@ module Fog
95
115
  Fog::Proxmox::Json.get_data(response)
96
116
  end
97
117
 
98
- def headers(method, additional_headers)
99
- additional_headers ||= {}
100
- headers_hash = { 'Accept' => 'application/json' }
101
- # CSRF token is required to PUT, POST and DELETE http requests
102
- if %w[PUT POST DELETE].include? method
103
- headers_hash.store('CSRFPreventionToken', @pve_csrftoken)
104
- end
105
- # ticket must be present in cookie
106
- headers_hash.store('Cookie', "PVEAuthCookie=#{@pve_ticket}") if @pve_ticket
107
- headers_hash.merge additional_headers
108
- headers_hash
109
- end
110
-
111
- def pve_options
112
- Fog::Proxmox::Variables.to_hash(self, 'pve')
118
+ def proxmox_options
119
+ Fog::Proxmox::Variables.to_hash(self, 'proxmox')
113
120
  end
114
121
 
115
122
  def authenticate
116
- options = pve_options
117
- @pve_ticket = options[:pve_ticket]
118
- Fog::Proxmox.authenticate(options, @connection_options)
119
- @principal = Fog::Proxmox.credentials
120
- @pve_username = Fog::Proxmox.credentials[:username]
121
- @pve_ticket = Fog::Proxmox.credentials[:ticket]
122
- @pve_deadline = Fog::Proxmox.credentials[:deadline]
123
- @pve_csrftoken = Fog::Proxmox.credentials[:csrftoken]
124
-
125
- @host = @pve_uri.host
126
- @api_path = @pve_uri.path
127
- @api_path.sub!(%r{/$}, '')
128
- @port = @pve_uri.port
129
- @scheme = @pve_uri.scheme
130
-
123
+ if @proxmox_must_reauthenticate
124
+ @token = nil if @proxmox_must_reauthenticate
125
+ @auth_token = Fog::Proxmox::Auth::Token.build(proxmox_options, @connection_options)
126
+ @current_user = proxmox_options[:proxmox_userid] ? proxmox_options[:proxmox_userid] : proxmox_options[:proxmox_username]
127
+ @token = @auth_token.token
128
+ @expires = @auth_token.expires
129
+ @proxmox_must_reauthenticate = false
130
+ else
131
+ @token = @proxmox_token
132
+ end
133
+ uri = URI.parse(@proxmox_url)
134
+ @path = uri.path
131
135
  true
132
136
  end
137
+
138
+ def authenticate!
139
+ @proxmox_must_reauthenticate = true
140
+ authenticate
141
+ end
133
142
  end
134
143
  end
135
144
  end
@@ -23,13 +23,13 @@ module Fog
23
23
  module Hash
24
24
 
25
25
  def self.stringify(hash)
26
- filtered = hash.reject { |_key,value| value.to_s.empty? }
26
+ filtered = hash.reject { |_key, value| value.nil? }
27
27
  a = filtered.to_a.collect { |item| item.join('=') }
28
28
  a.join(',')
29
29
  end
30
30
 
31
31
  def self.flatten(hash)
32
- filtered = hash.reject { |_key,value| value.to_s.empty? }
32
+ filtered = hash.reject { |_key, value| value.nil? }
33
33
  a = filtered.to_a.collect { |item| item.join(': ') }
34
34
  a.join(',')
35
35
  end
@@ -21,21 +21,60 @@ module Fog
21
21
  module Proxmox
22
22
  # module Cpu mixins
23
23
  module CpuHelper
24
- CPU_REGEXP = /(\bcputype=)?([\w-]+)[,]?(\bflags=)?(\+[\w-]+)?[;]?(\+[\w-]+)?/
25
- def self.extract(cpu,i)
26
- cpu ? CPU_REGEXP.match(cpu.to_s)[i] : ''
24
+ CPU_REGEXP = /(\bcputype=)?(?<cputype>[\w-]+)[,]?(\bflags=)?(?<flags>[[\+\-][\w-]+[;]?]*)/
25
+ FLAGS = { spectre: 'spec-ctrl', pcid: 'pcid', ssbd: 'ssbd', ibpb: 'ibpb', virt_ssbd: 'virt-ssbd', 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
+ def self.flags
27
+ FLAGS
28
+ end
29
+
30
+ def self.extract(cpu, name)
31
+ captures_h = cpu ? CPU_REGEXP.match(cpu.to_s) : { cputype: '', flags: '' }
32
+ captures_h[name]
33
+ end
34
+
35
+ def self.extract_cputype(cpu)
36
+ extract(cpu, :cputype)
37
+ end
38
+
39
+ def self.extract_flags(cpu)
40
+ extract(cpu, :flags)
41
+ end
42
+
43
+ def self.flag_value(cpu, flag_key)
44
+ flag_value = '0'
45
+ raw_values = extract_flags(cpu).split(';').select { |flag| ['+' + flag_key, '-' + flag_key].include?(flag) }
46
+ unless raw_values.empty?
47
+ flag_value = raw_values[0].start_with?('+') ? '+1' : raw_values[0].start_with?('-') ? '-1' : '0'
48
+ end
49
+ flag_value
27
50
  end
28
51
 
29
- def self.extract_type(cpu)
30
- extract(cpu,2)
52
+ def self.hash_has_no_default_flag?(cpu_h, flag_name)
53
+ cpu_h.key?(flag_name) && ['-1', '+1'].include?(cpu_h[flag_name])
31
54
  end
32
55
 
33
- def self.has_pcid?(cpu)
34
- extract(cpu,5) == '+pcid'
56
+ def self.hash_flag(cpu_h, flag_name)
57
+ flag = ''
58
+ if cpu_h.key?(flag_name)
59
+ flag = '+' if cpu_h[flag_name] == '+1'
60
+ flag = '-' if cpu_h[flag_name] == '-1'
61
+ end
62
+ flag
35
63
  end
36
64
 
37
- def self.has_spectre?(cpu)
38
- extract(cpu,4) == '+spec-ctrl'
65
+ def self.flatten(cpu_h)
66
+ return '' unless cpu_h['cpu_type']
67
+
68
+ cpu_type = "cputype=#{cpu_h['cpu_type']}"
69
+ num_flags = 0
70
+ FLAGS.each_key { |flag_key| num_flags += 1 if hash_has_no_default_flag?(cpu_h, flag_key.to_s) }
71
+ cpu_type += ',flags=' if num_flags > 0
72
+ flags_with_no_default_value = FLAGS.select { |flag_key, _flag_value| hash_has_no_default_flag?(cpu_h, flag_key.to_s) }
73
+ flags_with_no_default_value.each_with_index do |(flag_key, flag_value), index|
74
+ 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
+ cpu_type += ';' if num_flags > index + 1
76
+ end
77
+ cpu_type
39
78
  end
40
79
  end
41
80
  end
@@ -23,13 +23,15 @@ module Fog
23
23
  module Proxmox
24
24
  # module Disk mixins
25
25
  module DiskHelper
26
-
27
26
  DISKS_REGEXP = /^(scsi|sata|mp|rootfs|virtio|ide)(\d+){0,1}$/
28
27
  SERVER_DISK_REGEXP = /^(scsi|sata|virtio|ide)(\d+)$/
29
28
  MOUNT_POINT_REGEXP = /^(mp)(\d+)$/
30
29
  ROOTFS_REGEXP = /^(rootfs)$/
31
30
  CDROM_REGEXP = /^(.*)[,]{0,1}(media=cdrom)[,]{0,1}(.*)$/
31
+ TEMPLATE_REGEXP = /^(.*)(base-)(.*)$/
32
+ CLOUD_INIT_REGEXP = /^(.*)(cloudinit)(.*)$/
32
33
 
34
+ # Convert disk attributes hash into API Proxmox parameters string
33
35
  def self.flatten(disk)
34
36
  id = disk[:id]
35
37
  value = ''
@@ -42,12 +44,12 @@ module Fog
42
44
  value += 'none'
43
45
  end
44
46
  opts = disk[:options] if disk[:options]
45
- main_a = [:id,:volid,:storage,:size]
46
- opts = disk.reject { |key,_value| main_a.include? key } unless opts
47
+ main_a = [:id, :volid, :storage, :size]
48
+ opts ||= disk.reject { |key, _value| main_a.include? key }
47
49
  options = ''
48
50
  options += Fog::Proxmox::Hash.stringify(opts) if opts
49
- if id == 'ide2' && !self.cdrom?(options)
50
- options += ',' if !options.empty?
51
+ if id == 'ide2' && !cdrom?(options)
52
+ options += ',' unless options.empty?
51
53
  options += 'media=cdrom'
52
54
  end
53
55
  value += ',' if !options.empty? && !value.empty?
@@ -67,25 +69,26 @@ module Fog
67
69
  id.scan(/(\w+)(\d+)/).first
68
70
  end
69
71
 
72
+ # Convert API Proxmox parameter string into attribute hash value
70
73
  def self.extract_option(name, disk_value)
71
74
  values = disk_value.scan(/#{name}=(\w+)/)
72
75
  name_value = values.first if values
73
76
  name_value&.first
74
77
  end
75
78
 
79
+ # Convert API Proxmox volume/disk parameter string into volume/disk attributes hash value
76
80
  def self.extract_storage_volid_size(disk_value)
77
- #volid definition: <VOULME_ID>:=<STORAGE_ID>:<storage type dependent volume name>
81
+ # volid definition: <VOLUME_ID>:=<STORAGE_ID>:<storage type dependent volume name>
78
82
  values_a = disk_value.scan(/^(([\w-]+)[:]{0,1}([\w\/\.-]+))/)
79
83
  no_cdrom = !disk_value.match(CDROM_REGEXP)
80
84
  creation = disk_value.split(',')[0].match(/^(([\w-]+)[:]{1}([\d]+))$/)
81
85
  values = values_a.first if values_a
82
86
  if no_cdrom
87
+ storage = values[1]
83
88
  if creation
84
- storage = values[1]
85
89
  volid = nil
86
90
  size = values[2].to_i
87
91
  else
88
- storage = values[1]
89
92
  volid = values[0]
90
93
  size = extract_size(disk_value)
91
94
  end
@@ -98,16 +101,16 @@ module Fog
98
101
  end
99
102
 
100
103
  def self.to_bytes(size)
101
- val=size.match(/\d+(\w?)/)
102
- m=0
103
- case val[1]
104
- when "K" then m=1
105
- when "M" then m=2
106
- when "G" then m=3
107
- when "T" then m=4
108
- when "P" then m=5
104
+ val = size.match(/\d+(\w?)/)
105
+ m = 0
106
+ case val[1]
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
109
112
  end
110
- val[0].to_i*1024**m
113
+ val[0].to_i * 1024**m
111
114
  end
112
115
 
113
116
  def self.modulo_bytes(size)
@@ -115,20 +118,20 @@ module Fog
115
118
  end
116
119
 
117
120
  def self.to_human_bytes(size)
118
- units = ['Kb','Mb','Gb','Tb','Pb']
121
+ units = ['Kb', 'Mb', 'Gb', 'Tb', 'Pb']
119
122
  i = 0
120
123
  human_size = size.to_s + 'b'
121
124
  while i < 5 && size >= 1024
122
- size = self.modulo_bytes(size)
125
+ size = modulo_bytes(size)
123
126
  human_size = size.to_s + units[i]
124
- i+=1
127
+ i += 1
125
128
  end
126
129
  human_size
127
130
  end
128
131
 
129
132
  def self.extract_size(disk_value)
130
- size=extract_option('size', disk_value)
131
- size ? self.to_bytes(size) : "1G"
133
+ size = extract_option('size', disk_value)
134
+ size ? to_bytes(size) : "1G"
132
135
  end
133
136
 
134
137
  def self.disk?(id)
@@ -154,6 +157,23 @@ module Fog
154
157
  def self.container_disk?(id)
155
158
  rootfs?(id) || mount_point?(id)
156
159
  end
160
+
161
+ def self.template?(volid)
162
+ TEMPLATE_REGEXP.match(volid) ? true : false
163
+ end
164
+
165
+ def self.cloud_init?(volid)
166
+ CLOUD_INIT_REGEXP.match(volid) ? true : false
167
+ end
168
+
169
+ def self.of_type?(disk_h, vm_type)
170
+ id = disk_h['id'] if disk_h.key?('id')
171
+ id = disk_h[:id] if disk_h.key?(:id)
172
+ result = false
173
+ result = server_disk?(id) if vm_type == 'qemu'
174
+ result = container_disk?(id) if vm_type == 'lxc'
175
+ result
176
+ end
157
177
  end
158
178
  end
159
179
  end