foreman_fog_proxmox 0.13.4 → 0.14.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +63 -52
  3. data/app/assets/javascripts/foreman_fog_proxmox/proxmox_compute_resource.js +0 -2
  4. data/app/assets/javascripts/foreman_fog_proxmox/proxmox_vm.js +0 -1
  5. data/app/assets/javascripts/foreman_fog_proxmox/proxmox_vm_server.js +0 -2
  6. data/app/assets/javascripts/foreman_fog_proxmox/proxmox_volume_cloudinit.js +0 -1
  7. data/app/controllers/concerns/foreman_fog_proxmox/compute_resources_vms_controller.rb +17 -7
  8. data/app/controllers/concerns/foreman_fog_proxmox/controller/parameters/compute_resource.rb +1 -1
  9. data/app/controllers/concerns/foreman_fog_proxmox/hosts_controller.rb +58 -0
  10. data/app/controllers/foreman_fog_proxmox/compute_resources_controller.rb +6 -3
  11. data/app/helpers/proxmox_compute_controllers_helper.rb +2 -1
  12. data/app/helpers/proxmox_compute_resources_helper.rb +3 -3
  13. data/app/helpers/proxmox_compute_resources_vms_helper.rb +16 -7
  14. data/app/helpers/proxmox_form_helper.rb +10 -6
  15. data/app/helpers/proxmox_vm_config_helper.rb +16 -25
  16. data/app/helpers/proxmox_vm_interfaces_helper.rb +19 -6
  17. data/app/helpers/proxmox_vm_os_template_helper.rb +2 -5
  18. data/app/helpers/proxmox_vm_uuid_helper.rb +1 -1
  19. data/app/helpers/proxmox_vm_volumes_helper.rb +22 -25
  20. data/app/models/concerns/fog_extensions/proxmox/node.rb +2 -2
  21. data/app/models/concerns/fog_extensions/proxmox/server.rb +10 -6
  22. data/app/models/concerns/host_ext/proxmox/associator.rb +3 -2
  23. data/app/models/concerns/host_ext/proxmox/for_vm.rb +1 -1
  24. data/app/models/concerns/host_ext/proxmox/interfaces.rb +7 -3
  25. data/app/models/concerns/orchestration/proxmox/compute.rb +11 -4
  26. data/app/models/foreman_fog_proxmox/options_select.rb +1 -3
  27. data/app/models/foreman_fog_proxmox/proxmox.rb +12 -10
  28. data/app/models/foreman_fog_proxmox/proxmox_compute_attributes.rb +15 -3
  29. data/app/models/foreman_fog_proxmox/proxmox_connection.rb +6 -2
  30. data/app/models/foreman_fog_proxmox/proxmox_console.rb +3 -1
  31. data/app/models/foreman_fog_proxmox/proxmox_images.rb +2 -2
  32. data/app/models/foreman_fog_proxmox/proxmox_interfaces.rb +37 -14
  33. data/app/models/foreman_fog_proxmox/proxmox_operating_systems.rb +6 -1
  34. data/app/models/foreman_fog_proxmox/proxmox_pools.rb +4 -4
  35. data/app/models/foreman_fog_proxmox/proxmox_version.rb +7 -3
  36. data/app/models/foreman_fog_proxmox/proxmox_vm_commands.rb +9 -7
  37. data/app/models/foreman_fog_proxmox/proxmox_vm_new.rb +37 -24
  38. data/app/models/foreman_fog_proxmox/proxmox_vm_queries.rb +4 -5
  39. data/app/models/foreman_fog_proxmox/proxmox_volumes.rb +23 -12
  40. data/app/models/foreman_fog_proxmox/vms.rb +2 -2
  41. data/app/overrides/compute_resources_vms/form/add_clone_to_new_vm_compute_detail.rb +1 -1
  42. data/app/views/compute_resources_vms/form/proxmox/_add_from_profile_to_compute_form.html.erb +2 -2
  43. data/app/views/compute_resources_vms/form/proxmox/_add_from_profile_to_hosts_compute_detail_form.html.erb +4 -2
  44. data/app/views/compute_resources_vms/form/proxmox/_base.html.erb +0 -1
  45. data/app/views/compute_resources_vms/form/proxmox/container/_config.html.erb +2 -2
  46. data/app/views/compute_resources_vms/form/proxmox/container/_network.html.erb +1 -1
  47. data/app/views/compute_resources_vms/form/proxmox/container/_volume_mp.html.erb +1 -1
  48. data/app/views/compute_resources_vms/form/proxmox/container/_volume_rootfs.html.erb +1 -1
  49. data/app/views/compute_resources_vms/form/proxmox/server/_config.html.erb +3 -3
  50. data/app/views/compute_resources_vms/form/proxmox/server/_network.html.erb +2 -2
  51. data/app/views/compute_resources_vms/form/proxmox/server/_volume_hard_disk.html.erb +1 -1
  52. data/config/routes.rb +8 -4
  53. data/db/migrate/20210312105013_update_proxmox_uuid_host.rb +1 -2
  54. data/lib/foreman_fog_proxmox/engine.rb +5 -3
  55. data/lib/foreman_fog_proxmox/semver.rb +1 -4
  56. data/lib/foreman_fog_proxmox/version.rb +1 -1
  57. data/locale/en/foreman_fog_proxmox.po +140 -47
  58. data/locale/foreman_fog_proxmox.pot +300 -137
  59. data/locale/fr/foreman_fog_proxmox.po +145 -52
  60. data/test/factories/foreman_fog_proxmox/proxmox_container_mock_factory.rb +6 -7
  61. data/test/factories/foreman_fog_proxmox/proxmox_server_mock_factory.rb +6 -7
  62. data/test/functional/compute_resources_controller_test.rb +4 -2
  63. data/test/test_plugin_helper.rb +12 -7
  64. data/test/unit/foreman_fog_proxmox/helpers/proxmox_container_helper_test.rb +38 -47
  65. data/test/unit/foreman_fog_proxmox/helpers/proxmox_server_helper_test.rb +49 -34
  66. data/test/unit/foreman_fog_proxmox/helpers/proxmox_vm_helper_test.rb +29 -65
  67. data/test/unit/foreman_fog_proxmox/helpers/proxmox_vm_volumes_helper_test.rb +3 -3
  68. data/test/unit/foreman_fog_proxmox/proxmox_compute_attributes_test.rb +22 -13
  69. data/test/unit/foreman_fog_proxmox/proxmox_interfaces_test.rb +48 -37
  70. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_container_test.rb +45 -35
  71. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_server_create_test.rb +0 -4
  72. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_server_update_cdrom_test.rb +34 -22
  73. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_server_update_cloudinit_test.rb +20 -14
  74. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_server_update_hard_disk_test.rb +76 -54
  75. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_server_update_test.rb +26 -15
  76. data/test/unit/foreman_fog_proxmox/proxmox_vm_queries_test.rb +1 -1
  77. data/test/unit/foreman_fog_proxmox/semver_test.rb +2 -1
  78. metadata +36 -21
@@ -27,8 +27,14 @@ module ForemanFogProxmox
27
27
  end
28
28
 
29
29
  def set_nic_identifier(nic, index)
30
- nic.identifier = format('net%<index>s', index: index) if nic.identifier.empty?
31
- 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)
30
+ nic.compute_attributes[:id] = format('net%<index>s', index: index) if nic.compute_attributes[:id].empty?
31
+ unless Fog::Proxmox::NicHelper.nic?(nic.compute_attributes[:id])
32
+ raise ::Foreman::Exception,
33
+ _(format('Invalid proxmox NIC id on interface[%<index>s]. Must be net[n] with n integer >= 0',
34
+ index: index))
35
+ end
36
+
37
+ nic.identifier = nic.compute_attributes['id'] if nic.identifier.empty?
32
38
  end
33
39
 
34
40
  def vm_type(host)
@@ -47,7 +53,11 @@ module ForemanFogProxmox
47
53
 
48
54
  def set_container_interface_name(_host, nic, index)
49
55
  nic.compute_attributes['name'] = format('eth%<index>s', index: index) if nic.compute_attributes['name'].empty?
50
- raise ::Foreman::Exception, _(format('Invalid name interface[%<index>s]. Must be eth[n] with n integer >= 0', index: index)) unless container_nic_name_valid?(nic)
56
+ unless container_nic_name_valid?(nic)
57
+ raise ::Foreman::Exception,
58
+ _(format('Invalid name interface[%<index>s]. Must be eth[n] with n integer >= 0',
59
+ index: index))
60
+ end
51
61
  end
52
62
 
53
63
  def cidr_prefix(nic_compute_attributes, v6 = false)
@@ -64,7 +74,9 @@ module ForemanFogProxmox
64
74
  ipv = "IPv#{v6 ? '6' : '4'}"
65
75
  max = v6 ? 128 : 32
66
76
  checked = valid || ForemanFogProxmox::Value.empty?(ip)
67
- 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)
77
+ message = format(
78
+ '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
79
+ )
68
80
  raise ::Foreman::Exception, _(message) unless checked
69
81
  end
70
82
 
@@ -87,7 +99,10 @@ module ForemanFogProxmox
87
99
  ip = 'dhcp'
88
100
  elsif !ForemanFogProxmox::Value.empty?(cidr_prefix(nic_compute_attributes, v6))
89
101
  check_cidr(nic_compute_attributes, v6, ip)
90
- ip = Fog::Proxmox::IpHelper.send(to_cidr_method(v6), nic.send(ip_s(v6).to_sym), cidr_prefix(nic_compute_attributes, v6)) if ip
102
+ if ip
103
+ ip = Fog::Proxmox::IpHelper.send(to_cidr_method(v6), nic.send(ip_s(v6).to_sym),
104
+ cidr_prefix(nic_compute_attributes, v6))
105
+ end
91
106
  end
92
107
  end
93
108
  nic_compute_attributes[ip_s(v6).to_sym] = ip
@@ -112,17 +127,25 @@ module ForemanFogProxmox
112
127
  host.interfaces.select(&:physical?).each.with_index.reduce({}) do |hash, (nic, index)|
113
128
  set_nic_identifier(nic, index)
114
129
  set_container_interface_name(host, nic, index) if container?(host)
115
- nic_compute_attributes = nic.compute_attributes.merge(id: nic.identifier)
116
- ForemanFogProxmox::HashCollection.remove_empty_values(nic_compute_attributes)
130
+ ForemanFogProxmox::HashCollection.remove_empty_values(nic.compute_attributes)
117
131
  mac = nic.mac
118
132
  mac ||= nic.attributes['mac']
119
- set_mac(nic_compute_attributes, mac, vm_type(host)) if mac.present?
120
- interface_compute_attributes = host.compute_attributes['interfaces_attributes'] ? host.compute_attributes['interfaces_attributes'].select { |_k, v| v['id'] == nic.identifier } : {}
121
- nic_compute_attributes.store(:_delete, interface_compute_attributes[interface_compute_attributes.keys[0]]['_delete']) unless interface_compute_attributes.empty?
122
- set_ip(host, nic, nic_compute_attributes)
123
- set_ip(host, nic, nic_compute_attributes, true)
124
- ForemanFogProxmox::HashCollection.remove_keys(nic_compute_attributes, ['dhcp', 'dhcp6', 'cidr', 'cidr6'])
125
- hash.merge(index.to_s => nic_compute_attributes)
133
+ set_mac(nic.compute_attributes, mac, vm_type(host)) if mac.present?
134
+ interface_compute_attributes = if host.compute_attributes['interfaces_attributes']
135
+ host.compute_attributes['interfaces_attributes'].select do |_k, v|
136
+ v['id'] == nic.compute_attributes[:id]
137
+ end
138
+ else
139
+ {}
140
+ end
141
+ unless interface_compute_attributes.empty?
142
+ nic.compute_attributes.store(:_delete,
143
+ interface_compute_attributes[interface_compute_attributes.keys[0]]['_delete'])
144
+ end
145
+ set_ip(host, nic, nic.compute_attributes)
146
+ set_ip(host, nic, nic.compute_attributes, true)
147
+ ForemanFogProxmox::HashCollection.remove_keys(nic.compute_attributes, ['dhcp', 'dhcp6', 'cidr', 'cidr6'])
148
+ hash.merge(index.to_s => nic.compute_attributes)
126
149
  end
127
150
  end
128
151
  end
@@ -39,7 +39,12 @@ module ForemanFogProxmox
39
39
  end
40
40
 
41
41
  def os_linux_types_mapping(host)
42
- ['Debian', 'Redhat', 'Suse', 'Altlinux', 'Archlinux', 'Coreos', 'Rancheros', 'Gentoo'].include?(host.operatingsystem.type) ? available_linux_operating_systems : []
42
+ if ['Debian', 'Redhat', 'Suse', 'Altlinux', 'Archlinux', 'Coreos', 'Rancheros',
43
+ 'Gentoo'].include?(host.operatingsystem.type)
44
+ available_linux_operating_systems
45
+ else
46
+ []
47
+ end
43
48
  end
44
49
 
45
50
  def os_windows_types_mapping(host)
@@ -25,21 +25,21 @@ module ForemanFogProxmox
25
25
  end
26
26
 
27
27
  def pool_owner(vm)
28
- logger.debug(format(_('pool_owner(%<vmid>s)'), vmid: vm&.vmid))
28
+ logger.debug("pool_owner(#{vm&.vmid})")
29
29
  pools_owners = pools.select { |pool| pool.has_server?(vm&.vmid) }
30
30
  pool = pools_owners.first
31
- logger.debug(format(_('found vm: %<vmid>s member of pool: %<poolid>s'), vmid: vm&.vmid, poolid: pool&.poolid))
31
+ logger.debug("found vm: #{vm&.vmid} member of pool: #{pool&.poolid}")
32
32
  vm&.config&.pool = pool&.poolid
33
33
  end
34
34
 
35
35
  def add_vm_to_pool(poolid, vmid)
36
- logger.debug(format(_('add_vm_to_pool(%<poolid>s, %<vmid>s)'), poolid: poolid, vmid: vmid))
36
+ logger.debug("add_vm_to_pool(#{poolid}, #{vmid})")
37
37
  pool = identity_client.pools.get poolid
38
38
  pool&.add_server vmid
39
39
  end
40
40
 
41
41
  def remove_vm_from_pool(poolid, vmid)
42
- logger.debug(format(_('remove_vm_from_pool(%<poolid>s, %<vmid>s)'), poolid: poolid, vmid: vmid))
42
+ logger.debug("remove_vm_from_pool(#{poolid}, #{vmid})")
43
43
  pool = identity_client.pools.get poolid
44
44
  pool&.remove_server vmid
45
45
  end
@@ -22,8 +22,12 @@ require 'foreman_fog_proxmox/semver'
22
22
  module ForemanFogProxmox
23
23
  module ProxmoxVersion
24
24
  def version_suitable?
25
- logger.debug(format(_('Proxmox compute resource version is %<version>s'), version: version))
26
- raise ::Foreman::Exception, format(_('Proxmox version %<version>s is not semver suitable'), version: version) unless ForemanFogProxmox::Semver.semver?(version)
25
+ logger.debug("Proxmox compute resource version is #{version}")
26
+ unless ForemanFogProxmox::Semver.semver?(version)
27
+ raise ::Foreman::Exception,
28
+ format(_('Proxmox version %<version>s is not semver suitable'),
29
+ version: version)
30
+ end
27
31
 
28
32
  ForemanFogProxmox::Semver.to_semver(version) >= ForemanFogProxmox::Semver.to_semver('5.3.0')
29
33
  end
@@ -34,7 +38,7 @@ module ForemanFogProxmox
34
38
  rescue ::Foreman::Exception => e
35
39
  return 'Unkown' if e.message == 'User token expired'
36
40
  rescue StandardError => e
37
- logger.warn(format(_('failed to get identity client version: %<e>s'), e: e))
41
+ logger.warn("failed to get identity client version: #{e}")
38
42
  raise e
39
43
  end
40
44
  end
@@ -42,14 +42,13 @@ module ForemanFogProxmox
42
42
  if image_id
43
43
  clone_from_image(image_id, args, vmid)
44
44
  else
45
- convert_sizes(args)
46
45
  remove_volume_keys(args)
47
- logger.warn(format(_('create vm: args=%<args>s'), args: args))
46
+ logger.warn("create vm: args=#{args}")
48
47
  vm = node.send(vm_collection(type)).create(parse_typed_vm(args, type))
49
48
  start_on_boot(vm, args)
50
49
  end
51
50
  rescue StandardError => e
52
- logger.warn(format(_('failed to create vm: %<e>s'), e: e))
51
+ logger.warn("failed to create vm: #{e}")
53
52
  destroy_vm client.identity + '_' + vm.id if vm
54
53
  raise e
55
54
  end
@@ -74,7 +73,8 @@ module ForemanFogProxmox
74
73
  end
75
74
 
76
75
  def compute_config_attributes(parsed_attr)
77
- excluded_keys = [:vmid, :templated, :ostemplate, :ostemplate_file, :ostemplate_storage, :volumes_attributes, :pool]
76
+ excluded_keys = [:vmid, :templated, :ostemplate, :ostemplate_file, :ostemplate_storage, :volumes_attributes,
77
+ :pool]
78
78
  config_attributes = parsed_attr.reject { |key, _value| excluded_keys.include? key.to_sym }
79
79
  ForemanFogProxmox::HashCollection.remove_empty_values(config_attributes)
80
80
  config_attributes = config_attributes.reject { |key, _value| Fog::Proxmox::DiskHelper.disk?(key) }
@@ -90,11 +90,13 @@ module ForemanFogProxmox
90
90
  elsif vm.node_id != node_id
91
91
  vm.migrate(node_id)
92
92
  else
93
- convert_memory_sizes(new_attributes)
94
- parsed_attr = parse_typed_vm(ForemanFogProxmox::HashCollection.new_hash_reject_keys(new_attributes, ['volumes_attributes']).merge(type: vm.type), vm.type)
93
+ parsed_attr = parse_typed_vm(
94
+ ForemanFogProxmox::HashCollection.new_hash_reject_keys(new_attributes,
95
+ ['volumes_attributes']).merge(type: vm.type), vm.type
96
+ )
95
97
  config_attributes = compute_config_attributes(parsed_attr)
96
98
  volumes_attributes = new_attributes['volumes_attributes']
97
- logger.debug(format(_('save_vm(%<vmid>s) volumes_attributes=%<volumes_attributes>s'), vmid: uuid, volumes_attributes: volumes_attributes))
99
+ logger.debug("save_vm(#{uuid}) volumes_attributes=#{volumes_attributes}")
98
100
  volumes_attributes&.each_value { |volume_attributes| save_volume(vm, volume_attributes) }
99
101
  vm.update(config_attributes[:config_attributes])
100
102
  poolid = new_attributes['pool'] if new_attributes.key?('pool')
@@ -36,7 +36,7 @@ module ForemanFogProxmox
36
36
 
37
37
  def hard_disk_typed_defaults(vm_type)
38
38
  options = {}
39
- volume_attributes_h = { storage: storages.first.identity.to_s, size: (8 * GIGA) }
39
+ volume_attributes_h = { storage: storages.first.identity.to_s, size: '8' }
40
40
  case vm_type
41
41
  when 'qemu'
42
42
  controller = 'virtio'
@@ -74,8 +74,14 @@ module ForemanFogProxmox
74
74
 
75
75
  def interface_typed_defaults(type)
76
76
  interface_attributes_h = { id: 'net0', compute_attributes: {} }
77
- interface_attributes_h[:compute_attributes] = { model: 'virtio', bridge: bridges.first.identity.to_s } if type == 'qemu'
78
- interface_attributes_h[:compute_attributes] = { name: 'eth0', bridge: bridges.first.identity.to_s, dhcp: 1, dhcp6: 1 } if type == 'lxc'
77
+ if type == 'qemu'
78
+ interface_attributes_h[:compute_attributes] =
79
+ { model: 'virtio', bridge: bridges.first.identity.to_s }
80
+ end
81
+ if type == 'lxc'
82
+ interface_attributes_h[:compute_attributes] =
83
+ { name: 'eth0', bridge: bridges.first.identity.to_s, dhcp: 1, dhcp6: 1 }
84
+ end
79
85
  interface_attributes_h
80
86
  end
81
87
 
@@ -106,7 +112,7 @@ module ForemanFogProxmox
106
112
  interfaces_attributes = []
107
113
  interfaces_attributes.push(interface_typed_defaults(type))
108
114
  new_attr = new_attr.merge(interfaces_attributes: interfaces_attributes.map.with_index.to_h.invert)
109
- logger.debug(format(_('add_default_typed_interface(%<type>s) to new_attr=%<new_attr>s'), type: type, new_attr: new_attr))
115
+ logger.debug("add_default_typed_interface(#{type}) to new_attr=#{new_attr}")
110
116
  new_attr
111
117
  end
112
118
 
@@ -115,7 +121,7 @@ module ForemanFogProxmox
115
121
  volumes_attributes.push(hard_disk_typed_defaults('qemu'))
116
122
  volumes_attributes.push(hard_disk_typed_defaults('lxc'))
117
123
  new_attr = new_attr.merge(volumes_attributes: volumes_attributes.map.with_index.to_h.invert)
118
- logger.debug(format(_('add_default_typed_volume(%<type>s) to new_attr=%<new_attr>s'), type: type, new_attr: new_attr))
124
+ logger.debug("add_default_typed_volume(#{type}) to new_attr=#{new_attr}")
119
125
  new_attr
120
126
  end
121
127
 
@@ -127,29 +133,28 @@ module ForemanFogProxmox
127
133
  defaults = vm_instance_defaults
128
134
  defaults = defaults.merge(config_attributes: config_attributes(type))
129
135
  defaults = add_default_typed_volume(defaults)
130
- defaults = add_default_typed_interface(type, defaults)
131
- defaults
136
+ add_default_typed_interface(type, defaults)
132
137
  end
133
138
 
134
139
  def config_attributes(type = 'qemu')
135
140
  case type
136
141
  when 'qemu'
137
142
  config_attributes = {
138
- cores: 1,
139
- sockets: 1,
140
- kvm: 0,
143
+ cores: '1',
144
+ sockets: '1',
145
+ kvm: '0',
141
146
  vga: 'std',
142
- memory: 512 * MEGA,
147
+ memory: '1024',
143
148
  ostype: 'l26',
144
149
  cpu: 'cputype=kvm64',
145
150
  scsihw: 'virtio-scsi-pci',
146
- templated: 0
151
+ templated: '0',
147
152
  }
148
153
  config_attributes = config_attributes
149
154
  when 'lxc'
150
155
  config_attributes = {
151
- memory: 512 * MEGA,
152
- templated: 0
156
+ memory: '1024',
157
+ templated: '0',
153
158
  }
154
159
  end
155
160
  config_attributes
@@ -159,14 +164,21 @@ module ForemanFogProxmox
159
164
  new_attr = ActiveSupport::HashWithIndifferentAccess.new(new_attr)
160
165
  type = new_attr['type']
161
166
  type ||= 'qemu'
162
- vm = new_typed_vm(new_attr, type)
163
- vm
167
+ new_typed_vm(new_attr, type)
164
168
  end
165
169
 
166
170
  def convert_config_attributes(new_attr)
167
171
  config_attributes = new_attr[:config_attributes]
168
- config_attributes[:volumes_attributes] = Hash[config_attributes[:disks].each_with_index.map { |disk, idx| [idx.to_s, disk.attributes] }] if config_attributes.key?(:disks)
169
- config_attributes[:interfaces_attributes] = Hash[config_attributes[:interfaces].each_with_index.map { |interface, idx| [idx.to_s, interface_compute_attributes(interface.attributes)] }] if config_attributes.key?(:interfaces)
172
+ if config_attributes.key?(:disks)
173
+ config_attributes[:volumes_attributes] = Hash[config_attributes[:disks].each_with_index.map do |disk, idx|
174
+ [idx.to_s, disk.attributes]
175
+ end ]
176
+ end
177
+ if config_attributes.key?(:interfaces)
178
+ config_attributes[:interfaces_attributes] = Hash[config_attributes[:interfaces].each_with_index.map do |interface, idx|
179
+ [idx.to_s, interface_compute_attributes(interface.attributes)]
180
+ end ]
181
+ end
170
182
  config_attributes.delete_if { |key, _value| ['disks', 'interfaces'].include?(key) }
171
183
  end
172
184
 
@@ -177,14 +189,15 @@ module ForemanFogProxmox
177
189
  new_attr_type = new_attr['type']
178
190
  new_attr_type ||= new_attr['config_attributes']['type'] if new_attr.key?('config_attributes')
179
191
  new_attr_type ||= type
180
- logger.debug(format(_('new_typed_vm(%<type>s): new_attr_type=%<new_attr_type>s'), type: type, new_attr_type: new_attr_type))
181
- logger.debug(format(_('new_typed_vm(%<type>s): new_attr=%<new_attr>s'), type: type, new_attr: new_attr))
192
+ logger.debug("new_typed_vm(#{type}): new_attr_type=#{new_attr_type}")
193
+ logger.debug("new_typed_vm(#{type}): new_attr=#{new_attr}'")
182
194
  options = !new_attr.key?('vmid') || ForemanFogProxmox::Value.empty?(new_attr['vmid']) ? vm_typed_instance_defaults(type).merge(new_attr).merge(type: type) : new_attr
183
- logger.debug(format(_('new_typed_vm(%<type>s): options=%<options>s'), type: type, options: options))
195
+ logger.debug("new_typed_vm(#{type}): options=#{options}")
184
196
  vm_h = parse_typed_vm(options, type).deep_symbolize_keys
185
- logger.debug(format(_('new_typed_vm(%<type>s): vm_h=%<vm_h>s'), type: type, vm_h: vm_h))
186
- vm = node.send(vm_collection(type)).new(vm_h)
187
- vm
197
+ logger.debug("new_typed_vm(#{type}): vm_h=#{vm_h}")
198
+ vm_h = vm_h.merge(vm_typed_instance_defaults(type)) if vm_h.empty?
199
+ logger.debug(format(_('new_typed_vm(%<type>s) with vm_typed_instance_defaults: vm_h=%<vm_h>s'), type: type, vm_h: vm_h))
200
+ node.send(vm_collection(type)).new(vm_h)
188
201
  end
189
202
  end
190
203
  end
@@ -31,7 +31,7 @@ module ForemanFogProxmox
31
31
  node = client.nodes.get node_id
32
32
  node ||= default_node
33
33
  storages = node.storages.list_by_content_type type
34
- logger.debug(format(_('storages(): node_id %<node_id>s type %<type>s'), node_id: node_id, type: type))
34
+ logger.debug("storages(): node_id #{node_id} type #{type}")
35
35
  storages.sort_by(&:storage)
36
36
  end
37
37
 
@@ -61,10 +61,9 @@ module ForemanFogProxmox
61
61
  nodes.each do |node|
62
62
  vm = find_vm_in_servers_by_vmid(node.servers, vmid)
63
63
  vm ||= find_vm_in_servers_by_vmid(node.containers, vmid)
64
- unless vm.nil?
65
- logger.debug("found vm #{vmid} on node #{node.node}")
66
- break
67
- end
64
+ next if vm.nil?
65
+ logger.debug("found vm #{vmid} on node #{node.node}")
66
+ break
68
67
  end
69
68
  vm
70
69
  end
@@ -25,7 +25,7 @@ module ForemanFogProxmox
25
25
  include ProxmoxVmHelper
26
26
 
27
27
  def delete_volume(vm, id, volume_attributes)
28
- logger.info(format(_('vm %<vmid>s delete volume %<volume_id>s'), vmid: vm.identity, volume_id: id))
28
+ logger.info("vm #{vm.identity} delete volume #{id}")
29
29
  vm.detach(id)
30
30
  return unless volume_type?(volume_attributes, 'hard_disk')
31
31
 
@@ -36,7 +36,7 @@ module ForemanFogProxmox
36
36
  def volume_options(vm, id, volume_attributes)
37
37
  options = {}
38
38
  options.store(:mp, volume_attributes['mp']) if vm.container? && id != 'rootfs'
39
- options.store(:cache, volume_attributes['cache']) unless vm.container?
39
+ options.store(:cache, volume_attributes['cache']) unless vm.container? || volume_attributes['cache'].empty?
40
40
  options
41
41
  end
42
42
 
@@ -59,19 +59,19 @@ module ForemanFogProxmox
59
59
  end
60
60
 
61
61
  def extend_volume(vm, id, diff_size)
62
- extension = '+' + (diff_size / GIGA).to_s + 'G'
63
- logger.info(format(_('vm %<vmid>s extend volume %<volume_id>s to %<extension>s'), vmid: vm.identity, volume_id: id, extension: extension))
62
+ extension = "+#{diff_size}G"
63
+ logger.info("vm #{vm.identity} extend volume #{id} to #{extension}")
64
64
  vm.extend(id, extension)
65
65
  end
66
66
 
67
67
  def move_volume(id, vm, new_storage)
68
- logger.info(format(_('vm %<vmid>s move volume %<volume_id>s into %<new_storage>s'), vmid: vm.identity, volume_id: id, new_storage: new_storage))
68
+ logger.info("vm #{vm.identity} move volume #{id} into #{new_storage}")
69
69
  vm.move(id, new_storage)
70
70
  end
71
71
 
72
72
  def update_options(disk, vm, volume_attributes)
73
73
  options = volume_options(vm, disk.id, volume_attributes) if volume_type?(volume_attributes, 'hard_disk')
74
- logger.info(format(_('vm %<vmid>s update volume %<volume_id>s to %<options>s'), vmid: vm.identity, volume_id: disk.id, options: options))
74
+ logger.info("vm #{vm.identity} update volume #{disk.id} to #{options}")
75
75
  new_disk = { id: disk.id }
76
76
  new_disk[:volid] = disk.volid
77
77
  vm.attach(new_disk, options)
@@ -82,7 +82,12 @@ module ForemanFogProxmox
82
82
  if volume_type?(volume_attributes, 'cdrom')
83
83
  update_cdrom(vm, disk, volume_attributes)
84
84
  elsif volume_type?(volume_attributes, 'hard_disk')
85
- diff_size = volume_attributes['size'].to_i - disk.size if volume_attributes['size'] && disk.size
85
+ diff_size = volume_attributes['size'].to_i - disk.size.to_i if volume_attributes['size'] && disk.size
86
+ unless diff_size >= 0
87
+ raise ::Foreman::Exception,
88
+ format(_('Unable to shrink %<id>s size. Proxmox allows only increasing size.'), id: id)
89
+ end
90
+ diff_size = volume_attributes['size'].to_i - disk.size.to_i if volume_attributes['size'] && disk.size
86
91
  raise ::Foreman::Exception, format(_('Unable to shrink %<id>s size. Proxmox allows only increasing size.'), id: id) unless diff_size >= 0
87
92
 
88
93
  new_storage = volume_attributes['storage']
@@ -98,7 +103,13 @@ module ForemanFogProxmox
98
103
  end
99
104
 
100
105
  def volume_exists?(vm, volume_attributes)
101
- vm.attributes.key?(volume_attributes['id'])
106
+ disk = vm.config.disks.get(volume_attributes['id'])
107
+ exists = false
108
+ return exists unless disk
109
+
110
+ exists = !volume_attributes['volid'].empty? if disk.hard_disk? || disk.cloud_init?
111
+ exists = !volume_attributes['cdrom'].empty? if disk.cdrom?
112
+ exists
102
113
  end
103
114
 
104
115
  def volume_to_delete?(volume_attributes)
@@ -121,20 +132,20 @@ module ForemanFogProxmox
121
132
  if volume_type?(volume_attributes, 'hard_disk')
122
133
  options = volume_options(vm, id, volume_attributes)
123
134
  disk_attributes[:storage] = volume_attributes['storage']
124
- disk_attributes[:size] = (volume_attributes['size'].to_i / GIGA).to_s
135
+ disk_attributes[:size] = volume_attributes['size']
125
136
  elsif volume_type?(volume_attributes, 'cdrom')
126
137
  disk_attributes[:volid] = volume_attributes[:iso]
127
138
  elsif volume_type?(volume_attributes, 'cloud_init')
128
139
  disk_attributes[:storage] = volume_attributes['storage']
129
140
  disk_attributes[:volid] = "#{volume_attributes['storage']}:cloudinit"
130
141
  end
131
- logger.info(format(_('vm %<vmid>s add volume %<volume_id>s'), vmid: vm.identity, volume_id: id))
132
- logger.debug(format(_('add_volume(%<vmid>s) disk_attributes=%<disk_attributes>s'), vmid: vm.identity, disk_attributes: disk_attributes))
142
+ logger.info("vm #{vm.identity} add volume #{id}")
143
+ logger.debug("add_volume(#{vm.identity}) disk_attributes=#{disk_attributes}")
133
144
  vm.attach(disk_attributes, options)
134
145
  end
135
146
 
136
147
  def save_volume(vm, volume_attributes)
137
- logger.debug(format(_('save_volume(%<vmid>s) volume_attributes=%<volume_attributes>s'), vmid: vm.identity, volume_attributes: volume_attributes))
148
+ logger.debug("save_volume(#{vm.identity}) volume_attributes=#{volume_attributes}")
138
149
  id = extract_id(vm, volume_attributes)
139
150
  if volume_exists?(vm, volume_attributes)
140
151
  if volume_to_delete?(volume_attributes)
@@ -21,8 +21,8 @@ module ForemanFogProxmox
21
21
  class Vms
22
22
  attr_reader :items
23
23
 
24
- def each
25
- @items.each { |item| yield item }
24
+ def each(&block)
25
+ @items.each(&block)
26
26
  end
27
27
 
28
28
  # TODO: Pagination with filters
@@ -20,6 +20,6 @@ Deface::Override.new(
20
20
  :name => 'add_from_profile_to_compute_detail',
21
21
  :replace => "erb[loud]:contains('provider_partial')",
22
22
  :partial => 'compute_resources_vms/form/proxmox/add_from_profile_to_hosts_compute_detail_form',
23
- :original => '448e3b265e4dc1789f0efbbc6076e32216ac3a24',
23
+ :original => '8902a49136f750d781dcaa44e7ffa8a29c1a94df',
24
24
  :namespaced => true
25
25
  )
@@ -16,8 +16,8 @@ You should have received a copy of the GNU General Public License
16
16
  along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>. %>
17
17
  <% if compute_resource.class == ForemanFogProxmox::Proxmox %>
18
18
  <%= render :partial => provider_partial(compute_resource, 'base'),
19
- :locals => { :f => f, :compute_resource => compute_resource, :new_host => true, :new_vm => true, :hide_image => true, :from_profile => from_profile }.merge(args_for_compute_resource_partial(@host)) %>
19
+ :locals => { :f => f, :host => nil, :compute_resource => compute_resource, :new_host => true, :new_vm => true, :from_profile => from_profile } %>
20
20
  <% else %>
21
21
  <%= render :partial => provider_partial(compute_resource, 'base'),
22
- :locals => { :f => f, :compute_resource => compute_resource, :new_host => true, :new_vm => true, :hide_image => true }.merge(args_for_compute_resource_partial(@host)) %>
22
+ :locals => { :f => f, :host => nil, :compute_resource => compute_resource, :new_host => true, :new_vm => true } %>
23
23
  <% end %>
@@ -17,8 +17,10 @@ along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>. %>
17
17
 
18
18
  <% if compute_resource.class == ForemanFogProxmox::Proxmox %>
19
19
  <%= render :partial => provider_partial(compute_resource, 'base'),
20
- :locals => { :f => f, :compute_resource => compute_resource, :new_host => new_vm, :new_vm => new_vm, :from_profile => false }.merge(args_for_compute_resource_partial(@host)) %>
20
+ locals: { f: f, host: host, compute_resource: compute_resource, new_host: host.new_record?, new_vm: new_vm,
21
+ arch: host.architecture_id, os: host.operatingsystem_id, from_profile: false } %>
21
22
  <% else %>
22
23
  <%= render :partial => provider_partial(compute_resource, 'base'),
23
- :locals => { :f => f, :compute_resource => compute_resource, :new_host => new_vm, :new_vm => new_vm }.merge(args_for_compute_resource_partial(@host)) %>
24
+ locals: { f: f, host: host, compute_resource: compute_resource, new_host: host.new_record?, new_vm: new_vm,
25
+ arch: host.architecture_id, os: host.operatingsystem_id } %>
24
26
  <% end %>
@@ -16,7 +16,6 @@ You should have received a copy of the GNU General Public License
16
16
  along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>. %>
17
17
 
18
18
  <%= javascript_include_tag 'foreman_fog_proxmox/proxmox_vm', "data-turbolinks-track" => true %>
19
- <%= javascript_tag("$(document).on('ContentLoad', tfm.numFields.initAll)"); %>
20
19
 
21
20
  <%= select_f f, :type, proxmox_types_map, :id, :name, { }, :label => _('Type'), :label_size => "col-md-2", :required => true, :onchange => "vmTypeSelected()", :disabled => !new_vm %>
22
21
 
@@ -28,8 +28,8 @@ along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>. %>
28
28
  <%= counter_f f, :cpuunits, :class => "input-mini", :label => _('CPU units'), :label_size => "col-md-2" %>
29
29
  <% end %>
30
30
  <%= field_set_tag _("Memory"), :id => "container_config_memory", :class => 'hide', :disabled => !container do %>
31
- <%= byte_size_f f, :memory, :class => "input-mini", :label => _('Memory'), :label_size => "col-md-2" %>
32
- <%= byte_size_f f, :swap, :class => "input-mini", :label => _('Swap'), :label_size => "col-md-2" %>
31
+ <%= text_f f, :memory, :class => "input-mini", :label => _('Memory (MB)'), :label_size => "col-md-2" %>
32
+ <%= text_f f, :swap, :class => "input-mini", :label => _('Swap (MB)'), :label_size => "col-md-2" %>
33
33
  <% end %>
34
34
  <%= field_set_tag _("DNS"), :id => "container_config_dns", :class => 'hide', :disabled => !container do %>
35
35
  <%= text_f f, :hostname, :label => _('Hostname'), :label_size => "col-md-2", :disabled => true %>
@@ -19,7 +19,7 @@ along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>. %>
19
19
  <% index = f.index ? f.index.present? : 0 %>
20
20
 
21
21
  <%= field_set_tag _("Nic"), :id => "container_network_#{index}", :style => ('display: none;' unless container), :disabled => !container do %>
22
- <%= f.hidden_field :id if !new_vm %>
22
+ <%= text_f f, :id, :label => _('Identifier'), :label_size => "col-md-2", :required => true, :label_help => _("net[n] with n integer >= 0, e.g. net0") %>
23
23
  <%= text_f f, :name, :label => _('Name'), :label_size => "col-md-2", :required => true, :label_help => _("eth[n] with n integer >= 0, e.g. eth0") %>
24
24
  <%= checkbox_f f, :dhcp, :label => _('DHCP IPv4') %>
25
25
  <%= text_f f, :cidr, :label => _('CIDR IPv4'), :label_size => "col-md-2", :label_help => _("integer within [0..32]") %>
@@ -23,5 +23,5 @@ along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>. %>
23
23
  <%= select_f f, :storage, compute_resource.storages(node_id), :storage, :storage, { }, :label => _('Storage'), :label_size => "col-md-2" %>
24
24
  <%= text_f f, :mp, :label => _('Path'), :label_size => "col-md-2", :required => true, :help_inline => _("e.g. /path/to/") %>
25
25
  <%= text_f f, :device, :label => _('Device'), :label_size => "col-md-2", :class => ('hide' if f.object.rootfs?), :disabled => (!new_volume || f.object.rootfs?), :'data-soft-max' => 10 %>
26
- <%= byte_size_f f, :size, :class => "input-mini", :label => _("Size"), :label_size => "col-md-2" %>
26
+ <%= text_f f, :size, :class => "input-mini", :label => _("Size (GB)"), :label_size => "col-md-2" %>
27
27
  <% end %>
@@ -20,5 +20,5 @@ along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>. %>
20
20
  <%= field_set_tag _("Rootfs"), :id => "container_volume_rootfs", :class => ('hide' unless container), :disabled => !container do %>
21
21
  <%= f.hidden_field :volid if !new_vm %>
22
22
  <%= select_f f, :storage, compute_resource.storages(node_id), :storage, :storage, { }, :label => _('Storage'), :label_size => "col-md-2" %>
23
- <%= byte_size_f f, :size, :class => "input-mini", :label => _("Size"), :label_size => "col-md-2" %>
23
+ <%= text_f f, :size, :class => "input-mini", :label => _("Size (GB)"), :label_size => "col-md-2" %>
24
24
  <% end %>
@@ -45,9 +45,9 @@ along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>. %>
45
45
  <% end %>
46
46
  <% end %>
47
47
  <%= field_set_tag _("Memory"), :id => "server_config_memory", :class => 'hide', :disabled => !server do %>
48
- <%= byte_size_f f, :memory, :class => "input-mini", :label => _('Memory'), :label_size => "col-md-2" %>
49
- <%= byte_size_f f, :balloon, :class => "input-mini", :label => _('Minimum memory'), :label_size => "col-md-2" %>
50
- <%= counter_f f, :shares, :class => "input-mini", :label => _('Shares'), :label_size => "col-md-2" %>
48
+ <%= text_f f, :memory, :class => "input-mini", :label => _('Memory (MB)'), :label_size => "col-md-2" %>
49
+ <%= text_f f, :balloon, :class => "input-mini", :label => _('Minimum memory (MB)'), :label_size => "col-md-2" %>
50
+ <%= text_f f, :shares, :class => "input-mini", :label => _('Shares (MB)'), :label_size => "col-md-2" %>
51
51
  <% end %>
52
52
  <%= field_set_tag _("Operating System"), :id => "server_config_os", :class => 'hide', :disabled => !server do %>
53
53
  <%= select_f f, :ostype, proxmox_operating_systems_map, :id, :name, { :include_blank => true }, :label => _('OS type'), :label_size => "col-md-2" %>
@@ -18,8 +18,8 @@ along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>. %>
18
18
  <% server = vm_type == 'qemu' %>
19
19
  <% index = f.index ? f.index.present? : 0 %>
20
20
 
21
- <%= field_set_tag _("Nic"), :id => "server_network_#{index}", :style => ('display: none;' unless server), :disabled => !server do %>
22
- <%= f.hidden_field :id if !new_vm %>
21
+ <%= field_set_tag _("Nic"), :id => "server_network_#{index}", :style => ('display: none;' unless server), :disabled => !server do %>
22
+ <%= text_f f, :id, :label => _('Identifier'), :label_size => "col-md-2", :required => true, :label_help => _("net[n] with n integer >= 0, e.g. net0") %>
23
23
  <%= select_f f, :model, proxmox_networkcards_map, :id, :name, { }, :label => _('Card'), :label_size => "col-md-2" %>
24
24
  <%= select_f f, :bridge, compute_resource.bridges(node_id), :iface, :iface, { }, :label => _('Bridge'), :label_size => "col-md-2" %>
25
25
  <%= counter_f f, :tag, :class => "input-mini", :label => _('VLAN tag'), :label_size => "col-md-2" %>
@@ -28,5 +28,5 @@ along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>. %>
28
28
  <%= select_f f, :controller, proxmox_controllers_map, :id, :name, { }, :label => _('Controller'), :label_size => "col-md-2", :disabled => !new_volume, :onchange => 'controllerSelected(this)' %>
29
29
  <%= text_f f, :device, :label => _('Device'), :label_size => "col-md-2", :disabled => !new_volume, :'data-min' => 0, :'data-soft-max' => proxmox_max_device(f.object.controller), :onchange => 'deviceSelected(this)' %>
30
30
  <%= select_f f, :cache, proxmox_caches_map, :id, :name, { include_blank: true }, :label => _('Cache'), :label_size => "col-md-2" %>
31
- <%= byte_size_f f, :size, :class => "input-mini", :label => _("Size"), :label_size => "col-md-2" %>
31
+ <%= text_f f, :size, :class => "input-mini", :label => _("Size (GB)"), :label_size => "col-md-2", :disabled => !hard_disk %>
32
32
  <% end %>
data/config/routes.rb CHANGED
@@ -19,12 +19,16 @@
19
19
 
20
20
  Rails.application.routes.draw do
21
21
  namespace :foreman_fog_proxmox do
22
- match 'isos/:compute_resource_id/:node_id/:storage', :to => 'compute_resources#isos_by_id_and_node_and_storage', :via => 'get'
23
- match 'ostemplates/:compute_resource_id/:node_id/:storage', :to => 'compute_resources#ostemplates_by_id_and_node_and_storage', :via => 'get'
22
+ match 'isos/:compute_resource_id/:node_id/:storage', :to => 'compute_resources#isos_by_id_and_node_and_storage',
23
+ :via => 'get'
24
+ match 'ostemplates/:compute_resource_id/:node_id/:storage',
25
+ :to => 'compute_resources#ostemplates_by_id_and_node_and_storage', :via => 'get'
24
26
  match 'isos/:compute_resource_id/:node_id', :to => 'compute_resources#isos_by_id_and_node', :via => 'get'
25
- match 'ostemplates/:compute_resource_id/:node_id', :to => 'compute_resources#ostemplates_by_id_and_node', :via => 'get'
27
+ match 'ostemplates/:compute_resource_id/:node_id', :to => 'compute_resources#ostemplates_by_id_and_node',
28
+ :via => 'get'
26
29
  match 'storages/:compute_resource_id/:node_id', :to => 'compute_resources#storages_by_id_and_node', :via => 'get'
27
- match 'isostorages/:compute_resource_id/:node_id', :to => 'compute_resources#iso_storages_by_id_and_node', :via => 'get'
30
+ match 'isostorages/:compute_resource_id/:node_id', :to => 'compute_resources#iso_storages_by_id_and_node',
31
+ :via => 'get'
28
32
  match 'bridges/:compute_resource_id/:node_id', :to => 'compute_resources#bridges_by_id_and_node', :via => 'get'
29
33
  end
30
34
  end
@@ -1,6 +1,5 @@
1
1
  include ProxmoxVmUuidHelper
2
2
  class UpdateProxmoxUuidHost < ActiveRecord::Migration[6.0]
3
-
4
3
  def up
5
4
  execute(sql(:concat))
6
5
  end
@@ -9,7 +8,7 @@ class UpdateProxmoxUuidHost < ActiveRecord::Migration[6.0]
9
8
  execute(sql(:substring))
10
9
  end
11
10
 
12
- private
11
+ private
13
12
 
14
13
  def concat
15
14
  "concat(h.compute_resource_id, '_', h.uuid) "