foreman_fog_proxmox 0.11.1 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of foreman_fog_proxmox might be problematic. Click here for more details.

Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -3
  3. data/app/assets/javascripts/foreman_fog_proxmox/proxmox_compute_resource.js +24 -2
  4. data/app/assets/javascripts/foreman_fog_proxmox/proxmox_vm.js +124 -52
  5. data/app/assets/javascripts/foreman_fog_proxmox/proxmox_vm_server.js +0 -48
  6. data/app/assets/javascripts/foreman_fog_proxmox/proxmox_volume.js +39 -0
  7. data/app/assets/javascripts/foreman_fog_proxmox/proxmox_volume_cdrom.js +63 -0
  8. data/app/assets/javascripts/foreman_fog_proxmox/proxmox_volume_cloudinit.js +25 -0
  9. data/app/controllers/concerns/foreman_fog_proxmox/controller/parameters/compute_resource.rb +1 -1
  10. data/app/helpers/proxmox_compute_controllers_helper.rb +39 -0
  11. data/app/helpers/proxmox_compute_resources_helper.rb +49 -0
  12. data/app/helpers/proxmox_compute_selectors_helper.rb +11 -44
  13. data/app/helpers/proxmox_form_helper.rb +12 -4
  14. data/app/{models/concerns/fog_extensions/proxmox/volume.rb → helpers/proxmox_storages_helper.rb} +5 -8
  15. data/app/{models/foreman_fog_proxmox/proxmox_token_expiration.rb → helpers/proxmox_vm_cdrom_helper.rb} +15 -10
  16. data/app/helpers/proxmox_vm_cloudinit_helper.rb +43 -0
  17. data/app/helpers/proxmox_vm_config_helper.rb +159 -0
  18. data/app/helpers/proxmox_vm_helper.rb +24 -70
  19. data/app/helpers/proxmox_vm_interfaces_helper.rb +85 -0
  20. data/app/helpers/proxmox_vm_os_template_helper.rb +47 -0
  21. data/app/helpers/proxmox_vm_volumes_helper.rb +105 -0
  22. data/app/models/concerns/fog_extensions/proxmox/disk.rb +17 -2
  23. data/app/models/concerns/fog_extensions/proxmox/interface.rb +19 -4
  24. data/app/models/concerns/fog_extensions/proxmox/server.rb +8 -3
  25. data/app/models/concerns/fog_extensions/proxmox/server_config.rb +8 -30
  26. data/app/models/concerns/host_ext/proxmox/interfaces.rb +7 -2
  27. data/app/models/concerns/orchestration/proxmox/compute.rb +1 -0
  28. data/app/models/foreman_fog_proxmox/proxmox.rb +58 -15
  29. data/app/models/foreman_fog_proxmox/proxmox_compute_attributes.rb +20 -12
  30. data/app/models/foreman_fog_proxmox/proxmox_connection.rb +14 -9
  31. data/app/models/foreman_fog_proxmox/proxmox_images.rb +2 -1
  32. data/app/models/foreman_fog_proxmox/proxmox_interfaces.rb +53 -28
  33. data/app/models/foreman_fog_proxmox/proxmox_operating_systems.rb +1 -1
  34. data/app/models/foreman_fog_proxmox/proxmox_version.rb +7 -2
  35. data/app/models/foreman_fog_proxmox/proxmox_vm_commands.rb +19 -30
  36. data/app/models/foreman_fog_proxmox/proxmox_vm_new.rb +108 -94
  37. data/app/models/foreman_fog_proxmox/proxmox_vm_queries.rb +2 -1
  38. data/app/models/foreman_fog_proxmox/proxmox_volumes.rb +79 -22
  39. data/app/views/compute_resources/form/_proxmox.html.erb +23 -10
  40. data/app/views/compute_resources/show/_proxmox.html.erb +6 -6
  41. data/app/views/compute_resources_vms/form/proxmox/_add_vm_type_to_nic_provider_specific_form.html.erb +4 -2
  42. data/app/views/compute_resources_vms/form/proxmox/_add_vm_type_to_volumes_edit.html.erb +46 -29
  43. data/app/views/compute_resources_vms/form/proxmox/_base.html.erb +3 -3
  44. data/app/views/compute_resources_vms/form/proxmox/_removable_layout.html.erb +2 -1
  45. data/app/views/compute_resources_vms/form/proxmox/container/_network.html.erb +8 -7
  46. data/app/views/compute_resources_vms/form/proxmox/server/_advanced.html.erb +0 -2
  47. data/app/views/compute_resources_vms/form/proxmox/server/_config.html.erb +16 -14
  48. data/app/views/compute_resources_vms/form/proxmox/server/_network.html.erb +2 -2
  49. data/app/views/compute_resources_vms/form/proxmox/server/_volume_cdrom.html.erb +34 -0
  50. data/app/views/compute_resources_vms/form/proxmox/server/_volume_cloud_init.html.erb +29 -0
  51. data/app/views/compute_resources_vms/form/proxmox/server/{_volume.html.erb → _volume_hard_disk.html.erb} +7 -3
  52. data/app/views/compute_resources_vms/show/_proxmox.html.erb +2 -0
  53. data/lib/foreman_fog_proxmox/engine.rb +9 -10
  54. data/lib/foreman_fog_proxmox/hash_collection.rb +69 -0
  55. data/lib/foreman_fog_proxmox/version.rb +1 -1
  56. data/lib/tasks/foreman_fog_proxmox_tasks.rake +0 -3
  57. data/test/factories/foreman_fog_proxmox/proxmox_container_mock_factory.rb +20 -8
  58. data/test/factories/foreman_fog_proxmox/proxmox_node_mock_factory.rb +5 -5
  59. data/test/factories/foreman_fog_proxmox/proxmox_server_mock_factory.rb +17 -7
  60. data/test/factories/proxmox_factory.rb +4 -4
  61. data/test/functional/compute_resources_controller_test.rb +4 -4
  62. data/test/unit/foreman_fog_proxmox/helpers/proxmox_container_helper_test.rb +49 -29
  63. data/test/unit/foreman_fog_proxmox/helpers/proxmox_server_helper_test.rb +53 -30
  64. data/test/unit/foreman_fog_proxmox/helpers/proxmox_vm_helper_test.rb +22 -20
  65. data/test/unit/foreman_fog_proxmox/helpers/proxmox_vm_volumes_helper_test.rb +50 -0
  66. data/test/unit/foreman_fog_proxmox/proxmox_compute_attributes_test.rb +12 -5
  67. data/test/unit/foreman_fog_proxmox/proxmox_interfaces_test.rb +38 -10
  68. data/test/unit/foreman_fog_proxmox/proxmox_version_test.rb +10 -10
  69. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_container_test.rb +34 -24
  70. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_server_create_test.rb +21 -7
  71. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_server_update_cdrom_test.rb +181 -0
  72. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_server_update_cloudinit_test.rb +131 -0
  73. data/test/unit/foreman_fog_proxmox/{proxmox_vm_commands_server_update_volumes_test.rb → proxmox_vm_commands_server_update_hard_disk_test.rb} +45 -19
  74. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_server_update_test.rb +21 -21
  75. data/test/unit/foreman_fog_proxmox/proxmox_vm_new_test.rb +3 -3
  76. metadata +44 -27
  77. data/app/helpers/proxmox_container_helper.rb +0 -163
  78. data/app/helpers/proxmox_server_helper.rb +0 -155
@@ -35,8 +35,12 @@ module HostExt
35
35
  end
36
36
  end
37
37
 
38
- def cidr_ip(interface_attributes)
39
- Fog::Proxmox::IpHelper.to_cidr(interface_attributes['ip'], interface_attributes['compute_attributes']['cidr_suffix'])
38
+ def cidr_ip(interface_attributes, v = 4)
39
+ key_ip = 'ip'
40
+ key_ip += '6' if v == 6
41
+ key_cidr = 'cidr'
42
+ key_cidr += '6' if v == 6
43
+ Fog::Proxmox::IpHelper.to_cidr(interface_attributes[key_ip], interface_attributes['compute_attributes'][key_cidr])
40
44
  end
41
45
 
42
46
  def add_interface_to_compute_attributes(index, interface_attributes, compute_attributes)
@@ -45,6 +49,7 @@ module HostExt
45
49
  compute_attributes[index].store('_delete', interface_attributes['_destroy'])
46
50
  compute_attributes[index].store('macaddr', interface_attributes['mac'])
47
51
  compute_attributes[index].store('ip', cidr_ip(interface_attributes))
52
+ compute_attributes[index].store('ip6', cidr_ip(interface_attributes, 6))
48
53
  compute_attributes[index].merge!(interface_attributes['compute_attributes'].reject { |k, _v| k == 'id' })
49
54
  end
50
55
  end
@@ -25,6 +25,7 @@ module Orchestration
25
25
  def setComputeUpdate
26
26
  logger.info "Update Proxmox Compute instance for #{name}"
27
27
  final_compute_attributes = compute_attributes.merge(compute_resource.host_compute_attrs(self))
28
+ logger.debug("setComputeUpdate: final_compute_attributes=#{final_compute_attributes}")
28
29
  compute_resource.save_vm uuid, final_compute_attributes
29
30
  rescue StandardError => e
30
31
  failure format(_('Failed to update a compute %<compute_resource>s instance %<name>s: %<e>s'), :compute_resource => compute_resource, :name => name, :e => e), e
@@ -24,10 +24,7 @@ require 'foreman_fog_proxmox/value'
24
24
  module ForemanFogProxmox
25
25
  class Proxmox < ComputeResource
26
26
  include ProxmoxVmHelper
27
- include ProxmoxServerHelper
28
- include ProxmoxContainerHelper
29
27
  include ProxmoxConnection
30
- include ProxmoxTokenExpiration
31
28
  include ProxmoxVmNew
32
29
  include ProxmoxVmCommands
33
30
  include ProxmoxVmQueries
@@ -39,9 +36,11 @@ module ForemanFogProxmox
39
36
  include ProxmoxVersion
40
37
  include ProxmoxConsole
41
38
  validates :url, :format => { :with => URI::DEFAULT_PARSER.make_regexp }, :presence => true
39
+ validates :auth_method, :presence => true, inclusion: { in: ['access_ticket', 'user_token'], message: ->(value) do format('%<value>s is not a valid authentication method', { value: value }) end }
42
40
  validates :user, :format => { :with => /(\w+)[@]{1}(\w+)/ }, :presence => true
43
- validates :password, :presence => true
44
- before_create :test_connection
41
+ validates :password, :presence => true, if: :access_ticket?
42
+ validates :token_id, :presence => true, if: :user_token?
43
+ validates :token, :presence => true, if: :user_token?
45
44
 
46
45
  def provided_attributes
47
46
  super.merge(
@@ -95,35 +94,79 @@ module ForemanFogProxmox
95
94
  attrs[:ssl_verify_peer] = value
96
95
  end
97
96
 
98
- def renew
99
- attrs[:renew].blank? ? false : Foreman::Cast.to_bool(attrs[:renew])
97
+ def auth_method
98
+ attrs[:auth_method] || 'access_ticket'
100
99
  end
101
100
 
102
- def renew=(value)
103
- attrs[:renew] = value
101
+ def auth_method=(value)
102
+ attrs[:auth_method] = value
103
+ end
104
+
105
+ def token_id
106
+ attrs[:token_id]
107
+ end
108
+
109
+ def token_id=(value)
110
+ attrs[:token_id] = value
111
+ end
112
+
113
+ def token
114
+ attrs[:token]
115
+ end
116
+
117
+ def token=(value)
118
+ attrs[:token] = value
104
119
  end
105
120
 
106
121
  private
107
122
 
123
+ def fog_credentials
124
+ hash = {
125
+ proxmox_url: url,
126
+ proxmox_auth_method: auth_method || 'access_ticket',
127
+ connection_options: connection_options
128
+ }
129
+ if access_ticket?
130
+ hash[:proxmox_username] = user
131
+ hash[:proxmox_password] = password
132
+ end
133
+ if user_token?
134
+ hash[:proxmox_userid] = user
135
+ hash[:proxmox_token] = token
136
+ hash[:proxmox_tokenid] = token_id
137
+ end
138
+ hash
139
+ end
140
+
141
+ def token_expired?(e)
142
+ e.response.reason_phrase == 'token expired'
143
+ end
144
+
108
145
  def client
109
146
  @client ||= ::Fog::Proxmox::Compute.new(fog_credentials)
147
+ rescue Excon::Errors::Unauthorized => e
148
+ raise ::Foreman::Exception, 'User token expired' if token_expired?(e)
110
149
  rescue StandardError => e
111
- logger.error(e)
112
- raise ::Foreman::Exception, format(N_('Failed retrieving proxmox compute client caused by %<e>s'), e: e)
150
+ logger.warn(format(_('failed to create compute client: %<e>s'), e: e))
151
+ raise e
113
152
  end
114
153
 
115
154
  def identity_client
116
155
  @identity_client ||= ::Fog::Proxmox::Identity.new(fog_credentials)
156
+ rescue Excon::Errors::Unauthorized => e
157
+ raise ::Foreman::Exception, 'User token expired' if token_expired?(e)
117
158
  rescue StandardError => e
118
- logger.error(e)
119
- raise ::Foreman::Exception, format(N_('Failed retrieving proxmox identity client caused by %<e>s'), e: e)
159
+ logger.warn(format(_('failed to create identity client: %<e>s'), e: e))
160
+ raise e
120
161
  end
121
162
 
122
163
  def network_client
123
164
  @network_client ||= ::Fog::Proxmox::Network.new(fog_credentials)
165
+ rescue Excon::Errors::Unauthorized => e
166
+ raise ::Foreman::Exception, 'User token expired' if token_expired?(e)
124
167
  rescue StandardError => e
125
- logger.error(e)
126
- raise ::Foreman::Exception, format(N_('Failed retrieving proxmox network client caused by %<e>s'), e: e)
168
+ logger.warn(format(_('failed to create network client: %<e>s'), e: e))
169
+ raise e
127
170
  end
128
171
 
129
172
  def host
@@ -20,30 +20,38 @@
20
20
  module ForemanFogProxmox
21
21
  module ProxmoxComputeAttributes
22
22
  def host_compute_attrs(host)
23
- super.tap do |_attrs|
24
- ostype = host.compute_attributes['config_attributes']['ostype']
25
- type = host.compute_attributes['type']
26
- case type
27
- when 'lxc'
28
- host.compute_attributes['config_attributes'].store('hostname', host.name)
29
- when 'qemu'
30
- unless compute_os_types(host).include?(ostype)
31
- raise ::Foreman::Exception, format(_('Operating system family %<type>s is not consistent with %<ostype>s'), type: host.operatingsystem.type, ostype: ostype)
32
- end
23
+ ostype = host.compute_attributes['config_attributes']['ostype']
24
+ type = host.compute_attributes['type']
25
+ case type
26
+ when 'lxc'
27
+ host.compute_attributes['config_attributes'].store('hostname', host.name)
28
+ when 'qemu'
29
+ unless compute_os_types(host).include?(ostype)
30
+ raise ::Foreman::Exception, format(_('Operating system family %<type>s is not consistent with %<ostype>s'), type: host.operatingsystem.type, ostype: ostype)
33
31
  end
34
32
  end
33
+ super
35
34
  end
36
35
 
37
36
  def not_config_key?(vm, key)
38
37
  [:disks, :interfaces, :vmid, :node_id, :node, :type].include?(key) || !vm.config.respond_to?(key)
39
38
  end
40
39
 
40
+ def interface_compute_attributes(interface_attributes)
41
+ vm_attrs = ForemanFogProxmox::HashCollection.new_hash_reject_keys(interface_attributes, [:identifier, :mac])
42
+ vm_attrs[:dhcp] = interface_attributes[:ip] == 'dhcp' ? '1' : '0'
43
+ vm_attrs[:dhcp6] = interface_attributes[:ip6] == 'dhcp' ? '1' : '0'
44
+ vm_attrs
45
+ end
46
+
41
47
  def vm_compute_attributes(vm)
42
48
  vm_attrs = {}
49
+ vm_attrs = vm_attrs.merge(vmid: vm.identity, node_id: vm.node_id, type: vm.type)
43
50
  if vm.respond_to?(:config)
44
- vm_attrs = vm_attrs.merge(vmid: vm.identity, node_id: vm.node_id, type: vm.type)
45
51
  vm_attrs[:volumes_attributes] = Hash[vm.config.disks.each_with_index.map { |disk, idx| [idx.to_s, disk.attributes] }] if vm.config.respond_to?(:disks)
46
- vm_attrs[:interfaces_attributes] = Hash[vm.config.interfaces.each_with_index.map { |interface, idx| [idx.to_s, interface.attributes] }] if vm.config.respond_to?(:interfaces)
52
+ if vm.config.respond_to?(:interfaces)
53
+ vm_attrs[:interfaces_attributes] = Hash[vm.config.interfaces.each_with_index.map { |interface, idx| [idx.to_s, interface_compute_attributes(interface.attributes)] }]
54
+ end
47
55
  vm_attrs[:config_attributes] = vm.config.attributes.reject do |key, value|
48
56
  not_config_key?(vm, key) || ForemanFogProxmox::Value.empty?(value.to_s) || Fog::Proxmox::DiskHelper.disk?(key.to_s) || Fog::Proxmox::NicHelper.nic?(key.to_s)
49
57
  end
@@ -28,23 +28,28 @@ module ForemanFogProxmox
28
28
  opts
29
29
  end
30
30
 
31
- def fog_credentials
32
- credentials = { pve_url: url,
33
- pve_username: user,
34
- pve_password: password,
35
- connection_options: connection_options }
36
- ticket = Fog::Proxmox.credentials[:ticket]
37
- credentials.store(:pve_ticket, ticket) if renew
38
- credentials
31
+ def access_ticket?
32
+ auth_method == 'access_ticket'
33
+ end
34
+
35
+ def user_token?
36
+ auth_method == 'user_token'
39
37
  end
40
38
 
41
39
  def credentials_valid?
42
- errors[:url].empty? && errors[:user].empty? && errors[:user].include?('@') && errors[:password].empty? && errors[:node_id].empty?
40
+ errors[:url].empty? && errors[:auth_method].empty?
41
+ errors[:user].empty? && errors[:user].include?('@') && errors[:password].empty? && errors[:node_id].empty? if access_ticket?
42
+ errors[:user].empty? && errors[:user].include?('@') && errors[:token_id].empty? && errors[:token].empty? && errors[:node_id].empty? if user_token?
43
+ end
44
+
45
+ def current_user_token_expire
46
+ identity_client ? identity_client.expires : 0
43
47
  end
44
48
 
45
49
  def test_connection(options = {})
46
50
  super
47
51
  credentials_valid?
52
+ identity_client
48
53
  version_suitable?
49
54
  rescue StandardError => e
50
55
  errors[:base] << e.message
@@ -27,6 +27,7 @@ module ForemanFogProxmox
27
27
  node = client.nodes.get node_id
28
28
  node ||= default_node
29
29
  storage = node.storages.get storage_id if storage_id
30
+ logger.debug(format(_('images_by_storage(): node_id %<node_id>s storage_id %<storage_id>s type %<type>s'), node_id: node_id, storage_id: storage_id, type: type))
30
31
  storage.volumes.list_by_content_type(type).sort_by(&:volid) if storage
31
32
  end
32
33
 
@@ -40,7 +41,7 @@ module ForemanFogProxmox
40
41
  storage = storages(node.node).first
41
42
  volumes += storage.volumes.list_by_content_type('images')
42
43
  end
43
- volumes.select(&:templated?)
44
+ volumes.select(&:template?)
44
45
  end
45
46
 
46
47
  def template(vmid)
@@ -30,8 +30,14 @@ module ForemanFogProxmox
30
30
  raise ::Foreman::Exception, _(format('Invalid identifier interface[%<index>s]. Must be net[n] with n integer >= 0', index: index)) unless Fog::Proxmox::NicHelper.nic?(nic.identifier)
31
31
  end
32
32
 
33
+ def vm_type(host)
34
+ type = host.compute_attributes['type']
35
+ type ||= host.compute_attributes[:config_attributes].key?(:arch) ? 'lxc' : 'qemu'
36
+ type
37
+ end
38
+
33
39
  def container?(host)
34
- host.compute_attributes['type'] == 'lxc'
40
+ vm_type(host) == 'lxc'
35
41
  end
36
42
 
37
43
  def container_nic_name_valid?(nic)
@@ -44,32 +50,46 @@ module ForemanFogProxmox
44
50
  end
45
51
 
46
52
  def cidr_prefix(nic_compute_attributes, v6 = false)
47
- attr_name = 'cidrv'
48
- attr_name += v6 ? '6' : '4'
49
- attr_name += '_prefix'
50
- nic_compute_attributes[attr_name] if nic_compute_attributes[attr_name].presence
53
+ attr_name = "cidr#{v6_s(v6)}"
54
+ nic_compute_attributes[attr_name] if nic_compute_attributes.key?(attr_name)
51
55
  end
52
56
 
53
- def set_ip(host, nic, nic_compute_attributes, v6 = false)
54
- return 'dhcp' if dhcp?(nic_compute_attributes, v6)
55
-
56
- ip = v6 ? nic.ip6 : nic.ip
57
- return ip unless container?(host) || cidr_prefix(nic_compute_attributes, v6)
57
+ def cidr_prefix_method(v6)
58
+ "cidr#{v6_s(v6)}_prefix?".to_sym
59
+ end
58
60
 
59
- valid = v6 ? Fog::Proxmox::IpHelper.cidr6_prefix?(cidr_prefix(nic_compute_attributes, v6)) : Fog::Proxmox::IpHelper.cidr_prefix?(cidr_prefix(nic_compute_attributes, v6))
60
- ipv = v6 ? 'IPv6' : 'IPv4'
61
+ def check_cidr(nic_compute_attributes, v6, ip)
62
+ valid = Fog::Proxmox::IpHelper.send(cidr_prefix_method(v6), cidr_prefix(nic_compute_attributes, v6))
63
+ ipv = "IPv#{v6 ? '6' : '4'}"
61
64
  max = v6 ? 128 : 32
62
- unless valid
63
- raise ::Foreman::Exception, _(format('Invalid Interface Proxmox CIDR %<ip>s. If %<ip>s is not empty, Proxmox CIDR prefix must be an integer between 0 and %<max>i.', ip: ipv, max: max))
64
- end
65
+ checked = valid || ForemanFogProxmox::Value.empty?(ip)
66
+ message = format('Invalid Interface Proxmox CIDR %<ip>s. If %<ip>s is not empty, Proxmox CIDR prefix must be an integer between 0 and %<max>i.', ip: ipv, max: max)
67
+ raise ::Foreman::Exception, _(message) unless checked
68
+ end
65
69
 
66
- v6 ? Fog::Proxmox::IpHelper.to_cidr6(nic.ip6, cidr_prefix(nic_compute_attributes, v6)) : Fog::Proxmox::IpHelper.to_cidr(nic.ip, cidr_prefix(nic_compute_attributes, v6))
70
+ def v6_s(v6)
71
+ v6 ? '6' : ''
67
72
  end
68
73
 
69
- def set_gw(nic_compute_attributes, v6 = false)
70
- attr_name = 'gwv'
71
- attr_name += v6 ? '6' : '4'
72
- nic_compute_attributes[attr_name] if nic_compute_attributes[attr_name].presence
74
+ def ip_s(v6)
75
+ "ip#{v6_s(v6)}"
76
+ end
77
+
78
+ def to_cidr_method(v6)
79
+ "to_cidr#{v6_s(v6)}".to_sym
80
+ end
81
+
82
+ def set_ip(host, nic, nic_compute_attributes, v6 = false)
83
+ ip = nic.send(ip_s(v6).to_sym)
84
+ if container?(host)
85
+ if dhcp?(nic_compute_attributes, v6)
86
+ ip = 'dhcp'
87
+ elsif !ForemanFogProxmox::Value.empty?(cidr_prefix(nic_compute_attributes, v6))
88
+ check_cidr(nic_compute_attributes, v6, ip)
89
+ ip = Fog::Proxmox::IpHelper.send(to_cidr_method(v6), nic.send(ip_s(v6).to_sym), cidr_prefix(nic_compute_attributes, v6)) if ip
90
+ end
91
+ end
92
+ nic_compute_attributes[ip_s(v6).to_sym] = ip
73
93
  end
74
94
 
75
95
  def to_boolean(value)
@@ -77,9 +97,14 @@ module ForemanFogProxmox
77
97
  end
78
98
 
79
99
  def dhcp?(nic_compute_attributes, v6 = false)
80
- attr_name = 'dhcpv'
81
- attr_name += v6 ? '6' : '4'
82
- to_boolean(nic_compute_attributes[attr_name]) if nic_compute_attributes[attr_name].present?
100
+ attr_name = "dhcp#{v6_s(v6)}"
101
+ nic_compute_attributes.key?(attr_name) ? to_boolean(nic_compute_attributes[attr_name]) : false
102
+ end
103
+
104
+ def set_mac(nic_compute_attributes, mac, type)
105
+ mac_attr_name = { 'qemu' => :macaddr, 'lxc' => :hwaddr }
106
+ mac_key = mac_attr_name[type] || 'mac'
107
+ nic_compute_attributes[mac_key] = mac
83
108
  end
84
109
 
85
110
  def host_interfaces_attrs(host)
@@ -87,15 +112,15 @@ module ForemanFogProxmox
87
112
  set_nic_identifier(nic, index)
88
113
  set_container_interface_name(host, nic, index) if container?(host)
89
114
  nic_compute_attributes = nic.compute_attributes.merge(id: nic.identifier)
115
+ ForemanFogProxmox::HashCollection.remove_empty_values(nic_compute_attributes)
90
116
  mac = nic.mac
91
117
  mac ||= nic.attributes['mac']
92
- nic_compute_attributes.store(:macaddr, mac) if mac.present?
118
+ set_mac(nic_compute_attributes, mac, vm_type(host)) if mac.present?
93
119
  interface_compute_attributes = host.compute_attributes['interfaces_attributes'] ? host.compute_attributes['interfaces_attributes'].select { |_k, v| v['id'] == nic.identifier } : {}
94
120
  nic_compute_attributes.store(:_delete, interface_compute_attributes[interface_compute_attributes.keys[0]]['_delete']) unless interface_compute_attributes.empty?
95
- nic_compute_attributes.store(:ip, set_ip(host, nic, nic_compute_attributes))
96
- nic_compute_attributes.store(:gw, set_gw(nic_compute_attributes))
97
- nic_compute_attributes.store(:ip6, set_ip(host, nic, nic_compute_attributes, true))
98
- nic_compute_attributes.store(:gw6, set_gw(nic_compute_attributes, true))
121
+ set_ip(host, nic, nic_compute_attributes)
122
+ set_ip(host, nic, nic_compute_attributes, true)
123
+ ForemanFogProxmox::HashCollection.remove_keys(nic_compute_attributes, ['dhcp', 'dhcp6', 'cidr', 'cidr6'])
99
124
  hash.merge(index.to_s => nic_compute_attributes)
100
125
  end
101
126
  end
@@ -39,7 +39,7 @@ module ForemanFogProxmox
39
39
  end
40
40
 
41
41
  def os_linux_types_mapping(host)
42
- ['Debian', 'Redhat', 'Suse', 'Altlinux', 'Archlinux', 'CoreOs', 'Gentoo'].include?(host.operatingsystem.type) ? available_linux_operating_systems : []
42
+ ['Debian', 'Redhat', 'Suse', 'Altlinux', 'Archlinux', 'Coreos', 'Rancheros', 'Gentoo'].include?(host.operatingsystem.type) ? available_linux_operating_systems : []
43
43
  end
44
44
 
45
45
  def os_windows_types_mapping(host)
@@ -29,8 +29,13 @@ module ForemanFogProxmox
29
29
  end
30
30
 
31
31
  def version
32
- v = identity_client.read_version
33
- "#{v['version']}.#{v['release']}"
32
+ v = identity_client.read_version if identity_client
33
+ v ? v['version'] : 'Unknown'
34
+ rescue ::Foreman::Exception => e
35
+ return 'Unkown' if e.message == 'User token expired'
36
+ rescue StandardError => e
37
+ logger.warn(format(_('failed to get identity client version: %<e>s'), e: e))
38
+ raise e
34
39
  end
35
40
  end
36
41
  end
@@ -17,10 +17,13 @@
17
17
  # You should have received a copy of the GNU General Public License
18
18
  # along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>.
19
19
 
20
+ require 'foreman_fog_proxmox/hash_collection'
21
+
20
22
  module ForemanFogProxmox
21
23
  module ProxmoxVmCommands
22
24
  include ProxmoxVolumes
23
25
  include ProxmoxPools
26
+ include ProxmoxVmHelper
24
27
 
25
28
  def start_on_boot(vm, args)
26
29
  startonboot = args[:start_after_create].blank? ? false : Foreman::Cast.to_bool(args[:start_after_create])
@@ -32,6 +35,7 @@ module ForemanFogProxmox
32
35
  vmid = args[:vmid].to_i
33
36
  type = args[:type]
34
37
  node = client.nodes.get(args[:node_id])
38
+ vmid = node.servers.next_id.to_i if vmid < 1
35
39
  raise ::Foreman::Exception, format(N_('invalid vmid=%<vmid>s'), vmid: vmid) unless node.servers.id_valid?(vmid)
36
40
 
37
41
  image_id = args[:image_id]
@@ -39,15 +43,9 @@ module ForemanFogProxmox
39
43
  clone_from_image(image_id, args, vmid)
40
44
  else
41
45
  convert_sizes(args)
42
- remove_deletes(args)
43
- case type
44
- when 'qemu'
45
- vm = node.servers.create(parse_server_vm(args))
46
- when 'lxc'
47
- hash = parse_container_vm(args)
48
- hash = hash.merge(vmid: vmid)
49
- vm = node.containers.create(hash.reject { |key, _value| ['ostemplate_storage', 'ostemplate_file'].include? key })
50
- end
46
+ remove_volume_keys(args)
47
+ logger.warn(format(_('create vm: args=%<args>s'), args: args))
48
+ vm = node.send(vm_collection(type)).create(parse_typed_vm(args, type))
51
49
  start_on_boot(vm, args)
52
50
  end
53
51
  rescue StandardError => e
@@ -69,24 +67,18 @@ module ForemanFogProxmox
69
67
  true
70
68
  end
71
69
 
72
- def update_required?(old_attrs, new_attrs)
73
- return true if super(old_attrs, new_attrs)
74
-
75
- new_attrs[:interfaces_attributes]&.each do |key, interface|
76
- return true if (interface[:id].blank? || interface[:_delete] == '1') && key != 'new_interfaces' # ignore the template
77
- end
78
-
79
- new_attrs[:volumes_attributes]&.each do |key, volume|
80
- return true if (volume[:id].blank? || volume[:_delete] == '1') && key != 'new_volumes' # ignore the template
81
- end
82
-
83
- false
84
- end
85
-
86
70
  def user_data_supported?
87
71
  true
88
72
  end
89
73
 
74
+ def compute_config_attributes(parsed_attr)
75
+ excluded_keys = [:vmid, :templated, :ostemplate, :ostemplate_file, :ostemplate_storage, :volumes_attributes, :pool]
76
+ config_attributes = parsed_attr.reject { |key, _value| excluded_keys.include? key.to_sym }
77
+ ForemanFogProxmox::HashCollection.remove_empty_values(config_attributes)
78
+ config_attributes = config_attributes.reject { |key, _value| Fog::Proxmox::DiskHelper.disk?(key) }
79
+ { config_attributes: config_attributes }
80
+ end
81
+
90
82
  def save_vm(uuid, new_attributes)
91
83
  vm = find_vm_by_uuid(uuid)
92
84
  templated = new_attributes['templated']
@@ -97,15 +89,12 @@ module ForemanFogProxmox
97
89
  vm.migrate(node_id)
98
90
  else
99
91
  convert_memory_sizes(new_attributes)
92
+ parsed_attr = parse_typed_vm(ForemanFogProxmox::HashCollection.new_hash_reject_keys(new_attributes, ['volumes_attributes']).merge(type: vm.type), vm.type)
93
+ config_attributes = compute_config_attributes(parsed_attr)
100
94
  volumes_attributes = new_attributes['volumes_attributes']
95
+ logger.debug(format(_('save_vm(%<vmid>s) volumes_attributes=%<volumes_attributes>s'), vmid: uuid, volumes_attributes: volumes_attributes))
101
96
  volumes_attributes&.each_value { |volume_attributes| save_volume(vm, volume_attributes) }
102
- parsed_attr = vm.container? ? parse_container_vm(new_attributes.merge(type: vm.type)) : parse_server_vm(new_attributes.merge(type: vm.type))
103
- logger.debug("parsed_attr=#{parsed_attr}")
104
- config_attributes = parsed_attr.reject { |key, _value| [:vmid, :templated, :ostemplate, :ostemplate_file, :ostemplate_storage, :volumes_attributes, :pool].include? key.to_sym }
105
- config_attributes = config_attributes.reject { |_key, value| ForemanFogProxmox::Value.empty?(value) }
106
- cdrom_attributes = parsed_attr.select { |_key, value| Fog::Proxmox::DiskHelper.cdrom?(value.to_s) }
107
- config_attributes = config_attributes.reject { |key, _value| Fog::Proxmox::DiskHelper.disk?(key) }
108
- vm.update(config_attributes.merge(cdrom_attributes))
97
+ vm.update(config_attributes[:config_attributes])
109
98
  poolid = new_attributes['pool'] if new_attributes.key?('pool')
110
99
  update_pool(vm, poolid) if poolid
111
100
  end