foreman_fog_proxmox 0.8.0 → 0.8.2

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 (93) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -1
  3. data/Rakefile +3 -1
  4. data/app/controllers/concerns/foreman_fog_proxmox/controller/parameters/compute_resource.rb +2 -2
  5. data/app/controllers/foreman_fog_proxmox/compute_resources_controller.rb +2 -2
  6. data/app/helpers/node_dashboard_helper.rb +13 -14
  7. data/app/helpers/proxmox_compute_selectors_helper.rb +49 -50
  8. data/app/helpers/proxmox_container_helper.rb +42 -36
  9. data/app/helpers/proxmox_form_helper.rb +38 -40
  10. data/app/helpers/proxmox_server_helper.rb +39 -41
  11. data/app/helpers/proxmox_vm_helper.rb +21 -25
  12. data/app/models/concerns/fog_extensions/proxmox/disk.rb +8 -8
  13. data/app/models/concerns/fog_extensions/proxmox/interface.rb +8 -8
  14. data/app/models/concerns/fog_extensions/proxmox/node.rb +24 -22
  15. data/app/models/concerns/fog_extensions/proxmox/server.rb +71 -59
  16. data/app/models/concerns/fog_extensions/proxmox/server_config.rb +47 -39
  17. data/app/models/concerns/fog_extensions/proxmox/volume.rb +8 -8
  18. data/app/models/concerns/host_ext/proxmox/interfaces.rb +21 -13
  19. data/app/models/concerns/orchestration/proxmox/compute.rb +14 -10
  20. data/app/models/foreman_fog_proxmox/options_select.rb +14 -14
  21. data/app/models/foreman_fog_proxmox/proxmox.rb +30 -466
  22. data/app/models/foreman_fog_proxmox/proxmox_compute_attributes.rb +54 -0
  23. data/app/models/foreman_fog_proxmox/proxmox_connection.rb +67 -0
  24. data/app/models/foreman_fog_proxmox/proxmox_console.rb +41 -0
  25. data/app/models/foreman_fog_proxmox/proxmox_images.rb +53 -0
  26. data/app/models/foreman_fog_proxmox/proxmox_interfaces.rb +60 -0
  27. data/app/models/foreman_fog_proxmox/proxmox_operating_systems.rb +49 -0
  28. data/app/models/foreman_fog_proxmox/proxmox_token_expiration.rb +30 -0
  29. data/app/models/foreman_fog_proxmox/proxmox_version.rb +36 -0
  30. data/app/models/foreman_fog_proxmox/proxmox_vm_commands.rb +108 -0
  31. data/app/models/foreman_fog_proxmox/proxmox_vm_new.rb +162 -0
  32. data/app/models/foreman_fog_proxmox/proxmox_vm_queries.rb +74 -0
  33. data/app/models/foreman_fog_proxmox/proxmox_volumes.rb +85 -0
  34. data/app/overrides/compute_resources_vms/form/add_clone_to_new_vm_compute_detail.rb +7 -6
  35. data/app/overrides/compute_resources_vms/form/add_from_profile_to_compute_attributes_form.rb +13 -11
  36. data/app/overrides/compute_resources_vms/form/add_vm_type_to_networks_form.rb +13 -11
  37. data/app/overrides/compute_resources_vms/form/add_vm_type_to_nic_provider_specific_form.rb +8 -7
  38. data/app/overrides/compute_resources_vms/form/add_vm_type_to_volumes_edit.rb +7 -6
  39. data/app/overrides/compute_resources_vms/form/add_vm_type_to_volumes_new_volume.rb +7 -6
  40. data/app/overrides/compute_resources_vms/form/remove_new_vm_from_removable_layout.rb +7 -6
  41. data/app/services/foreman_fog_proxmox/node_dashboard/data.rb +16 -16
  42. data/app/views/api/v2/compute_resources/proxmox.json.rabl +3 -1
  43. data/app/views/compute_resources/form/_proxmox.html.erb +3 -0
  44. data/app/views/compute_resources/show/_proxmox.html.erb +8 -0
  45. data/app/views/compute_resources_vms/form/proxmox/_add_from_profile_to_compute_attributes_form.html.erb +5 -0
  46. data/app/views/compute_resources_vms/form/proxmox/_add_from_profile_to_compute_form.html.erb +6 -1
  47. data/app/views/compute_resources_vms/form/proxmox/_add_from_profile_to_hosts_compute_detail_form.html.erb +6 -0
  48. data/app/views/compute_resources_vms/form/proxmox/_add_vm_type_to_networks_form.html.erb +6 -2
  49. data/app/views/compute_resources_vms/form/proxmox/_add_vm_type_to_networks_new_childs_form.html.erb +8 -2
  50. data/app/views/compute_resources_vms/form/proxmox/_add_vm_type_to_nic_provider_specific_form.html.erb +6 -0
  51. data/app/views/compute_resources_vms/form/proxmox/_add_vm_type_to_volumes_edit.html.erb +15 -1
  52. data/app/views/compute_resources_vms/form/proxmox/_base.html.erb +2 -2
  53. data/app/views/compute_resources_vms/form/proxmox/_general.html.erb +1 -1
  54. data/app/views/compute_resources_vms/form/proxmox/_removable_layout.html.erb +6 -1
  55. data/app/views/compute_resources_vms/form/proxmox/container/_extended.html.erb +1 -1
  56. data/app/views/compute_resources_vms/form/proxmox/container/_volume_mp.html.erb +1 -1
  57. data/app/views/compute_resources_vms/form/proxmox/server/_config.html.erb +1 -1
  58. data/app/views/compute_resources_vms/form/proxmox/server/_volume.html.erb +2 -2
  59. data/config/routes.rb +4 -4
  60. data/lib/foreman_fog_proxmox/engine.rb +14 -14
  61. data/lib/foreman_fog_proxmox/semver.rb +78 -78
  62. data/lib/foreman_fog_proxmox/value.rb +5 -3
  63. data/lib/foreman_fog_proxmox/version.rb +1 -1
  64. data/lib/tasks/foreman_fog_proxmox_tasks.rake +3 -13
  65. data/locale/en/foreman_fog_proxmox.edit.po +472 -0
  66. data/locale/en/foreman_fog_proxmox.po +48 -24
  67. data/locale/en/foreman_fog_proxmox.po.time_stamp +0 -0
  68. data/locale/foreman_fog_proxmox.pot +140 -102
  69. data/locale/fr/foreman_fog_proxmox.edit.po +472 -0
  70. data/locale/fr/foreman_fog_proxmox.po +52 -28
  71. data/locale/fr/foreman_fog_proxmox.po.time_stamp +0 -0
  72. data/locale/gemspec.rb +2 -0
  73. data/test/{unit/foreman_fog_proxmox/proxmox_test_helpers.rb → factories/foreman_fog_proxmox/proxmox_container_mock_factory.rb} +4 -140
  74. data/test/factories/foreman_fog_proxmox/proxmox_node_mock_factory.rb +61 -0
  75. data/test/factories/foreman_fog_proxmox/proxmox_server_mock_factory.rb +134 -0
  76. data/test/factories/proxmox_factory.rb +15 -15
  77. data/test/functional/compute_resources_controller_test.rb +12 -10
  78. data/test/test_plugin_helper.rb +2 -0
  79. data/test/unit/foreman_fog_proxmox/helpers/proxmox_container_helper_test.rb +178 -182
  80. data/test/unit/foreman_fog_proxmox/helpers/proxmox_server_helper_test.rb +122 -126
  81. data/test/unit/foreman_fog_proxmox/helpers/proxmox_vm_helper_test.rb +180 -187
  82. data/test/unit/foreman_fog_proxmox/proxmox_compute_attributes_test.rb +116 -0
  83. data/test/unit/foreman_fog_proxmox/proxmox_interfaces_test.rb +71 -0
  84. data/test/unit/foreman_fog_proxmox/proxmox_test.rb +9 -479
  85. data/test/unit/foreman_fog_proxmox/proxmox_version_test.rb +82 -0
  86. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_container_test.rb +207 -0
  87. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_server_create_test.rb +92 -0
  88. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_server_update_test.rb +324 -0
  89. data/test/unit/foreman_fog_proxmox/proxmox_vm_commands_test.rb +43 -0
  90. data/test/unit/foreman_fog_proxmox/proxmox_vm_new_test.rb +71 -0
  91. data/test/unit/foreman_fog_proxmox/proxmox_vm_queries_test.rb +63 -0
  92. data/test/unit/foreman_fog_proxmox/semver_test.rb +67 -53
  93. metadata +52 -14
@@ -20,44 +20,52 @@
20
20
  require 'fog/proxmox/helpers/cpu_helper'
21
21
 
22
22
  module FogExtensions
23
- module Proxmox
24
- module ServerConfig
25
- extend ActiveSupport::Concern
26
- def cpu_type
27
- Fog::Proxmox::CpuHelper.extract_type(cpu)
28
- end
29
- def spectre
30
- Fog::Proxmox::CpuHelper.extract_spectre(cpu)
31
- end
32
- def pcid
33
- Fog::Proxmox::CpuHelper.extract_pcid(cpu)
34
- end
35
- def cdrom
36
- if disks.cdrom
37
- %w[none cdrom].include?(disks.cdrom.volid) ? disks.cdrom.volid : 'image'
38
- else
39
- 'none'
40
- end
41
- end
42
- def cdrom_storage
43
- disks.cdrom ? disks.cdrom.storage : ''
44
- end
45
- def cdrom_iso
46
- disks.cdrom ? disks.cdrom.volid : ''
47
- end
48
- def cdrom_image
49
- if disks.cdrom
50
- %w[none cdrom].include?(disks.cdrom.volid) ? disks.cdrom.volid : 'image'
51
- else
52
- 'none'
53
- end
54
- end
55
- def rootfs_storage
56
- disks.rootfs.storage if disks.rootfs
57
- end
58
- def rootfs_file
59
- disks.rootfs.volid if disks.rootfs
60
- end
23
+ module Proxmox
24
+ module ServerConfig
25
+ extend ActiveSupport::Concern
26
+ def cpu_type
27
+ Fog::Proxmox::CpuHelper.extract_type(cpu)
28
+ end
29
+
30
+ def spectre
31
+ Fog::Proxmox::CpuHelper.has_spectre?(cpu)
32
+ end
33
+
34
+ def pcid
35
+ Fog::Proxmox::CpuHelper.has_pcid?(cpu)
36
+ end
37
+
38
+ def cdrom
39
+ if disks.cdrom
40
+ ['none', 'cdrom'].include?(disks.cdrom.volid) ? disks.cdrom.volid : 'image'
41
+ else
42
+ 'none'
61
43
  end
44
+ end
45
+
46
+ def cdrom_storage
47
+ disks.cdrom ? disks.cdrom.storage : ''
48
+ end
49
+
50
+ def cdrom_iso
51
+ disks.cdrom ? disks.cdrom.volid : ''
52
+ end
53
+
54
+ def cdrom_image
55
+ if disks.cdrom
56
+ ['none', 'cdrom'].include?(disks.cdrom.volid) ? disks.cdrom.volid : 'image'
57
+ else
58
+ 'none'
59
+ end
60
+ end
61
+
62
+ def rootfs_storage
63
+ disks.rootfs&.storage
64
+ end
65
+
66
+ def rootfs_file
67
+ disks.rootfs&.volid
68
+ end
62
69
  end
63
- end
70
+ end
71
+ end
@@ -18,12 +18,12 @@
18
18
  # along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>.
19
19
 
20
20
  module FogExtensions
21
- module Proxmox
22
- module Volume
23
- extend ActiveSupport::Concern
24
- def templated?
25
- volid ? volid.match(/^([\w-]+)[:]base-(\d+)-disk-(\d+)/) : false
26
- end
27
- end
21
+ module Proxmox
22
+ module Volume
23
+ extend ActiveSupport::Concern
24
+ def templated?
25
+ volid ? volid.match(/^([\w-]+)[:]base-(\d+)-disk-(\d+)/) : false
26
+ end
28
27
  end
29
- end
28
+ end
29
+ end
@@ -17,21 +17,29 @@
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
- module HostExt::Proxmox::Interfaces
21
- extend ActiveSupport::Concern
22
- def update(attributes = {})
20
+ module HostExt
21
+ module Proxmox
22
+ module Interfaces
23
+ extend ActiveSupport::Concern
24
+ def update(attributes = {})
23
25
  add_interfaces_to_compute_attributes(attributes)
24
26
  super(attributes)
25
- end
26
- def add_interfaces_to_compute_attributes(attributes)
27
+ end
28
+
29
+ def add_interfaces_to_compute_attributes(attributes)
27
30
  attributes['compute_attributes']['interfaces_attributes'] = {}
28
- attributes['interfaces_attributes'].each { |index,interface_attributes| add_interface_to_compute_attributes(index,interface_attributes,attributes['compute_attributes']['interfaces_attributes']) }
29
- end
30
- def add_interface_to_compute_attributes(index,interface_attributes,compute_attributes)
31
+ attributes['interfaces_attributes'].each do |index, interface_attributes|
32
+ add_interface_to_compute_attributes(index, interface_attributes, attributes['compute_attributes']['interfaces_attributes'])
33
+ end
34
+ end
35
+
36
+ def add_interface_to_compute_attributes(index, interface_attributes, compute_attributes)
31
37
  compute_attributes[index] = {}
32
- compute_attributes[index].store('id',interface_attributes['identifier'])
33
- compute_attributes[index].store('_delete',interface_attributes['_destroy'])
34
- compute_attributes[index].store('macaddr',interface_attributes['mac'])
35
- compute_attributes[index].merge!(interface_attributes['compute_attributes'].reject { |k,_v| k == 'id' })
38
+ compute_attributes[index].store('id', interface_attributes['identifier'])
39
+ compute_attributes[index].store('_delete', interface_attributes['_destroy'])
40
+ compute_attributes[index].store('macaddr', interface_attributes['mac'])
41
+ compute_attributes[index].merge!(interface_attributes['compute_attributes'].reject { |k, _v| k == 'id' })
42
+ end
36
43
  end
37
- end
44
+ end
45
+ end
@@ -17,22 +17,26 @@
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
- module Orchestration::Proxmox::Compute
21
- extend ActiveSupport::Concern
20
+ module Orchestration
21
+ module Proxmox
22
+ module Compute
23
+ extend ActiveSupport::Concern
22
24
 
23
- def setComputeUpdate
25
+ def setComputeUpdate
24
26
  logger.info "Update Proxmox Compute instance for #{name}"
25
27
  final_compute_attributes = compute_attributes.merge(compute_resource.host_compute_attrs(self))
26
28
  compute_resource.save_vm uuid, final_compute_attributes
27
- rescue => e
28
- failure _("Failed to update a compute %{compute_resource} instance %{name}: %{e}") % { :compute_resource => compute_resource, :name => name, :e => e }, e
29
- end
29
+ rescue StandardError => e
30
+ failure format(_('Failed to update a compute %<compute_resource>s instance %<name>s: %<e>s'), :compute_resource => compute_resource, :name => name, :e => e), e
31
+ end
30
32
 
31
- def delComputeUpdate
33
+ def delComputeUpdate
32
34
  logger.info "Undo Update Proxmox Compute instance for #{name}"
33
35
  final_compute_attributes = old.compute_attributes.merge(compute_resource.host_compute_attrs(old))
34
36
  compute_resource.save_vm uuid, final_compute_attributes
35
- rescue => e
36
- failure _("Failed to undo update compute %{compute_resource} instance %{name}: %{e}") % { :compute_resource => compute_resource, :name => name, :e => e }, e
37
+ rescue StandardError => e
38
+ failure format(_('Failed to undo update compute %<compute_resource>s instance %<name>s: %<e>s'), :compute_resource => compute_resource, :name => name, :e => e), e
39
+ end
37
40
  end
38
- end
41
+ end
42
+ end
@@ -18,19 +18,19 @@
18
18
  # along with ForemanFogProxmox. If not, see <http://www.gnu.org/licenses/>.
19
19
 
20
20
  module ForemanFogProxmox
21
- class OptionsSelect
22
- attr_accessor :id
23
- attr_accessor :name
24
- attr_accessor :range
25
-
26
- def to_s
27
- id
28
- end
29
-
30
- def initialize(args = {})
31
- @id = args[:id]
32
- @name = args[:name]
33
- @range = args[:range]
34
- end
21
+ class OptionsSelect
22
+ attr_accessor :id
23
+ attr_accessor :name
24
+ attr_accessor :range
25
+
26
+ def to_s
27
+ id
28
+ end
29
+
30
+ def initialize(args = {})
31
+ @id = args[:id]
32
+ @name = args[:name]
33
+ @range = args[:range]
35
34
  end
35
+ end
36
36
  end
@@ -17,10 +17,8 @@
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 'fog/proxmox'
21
20
  require 'fog/proxmox/helpers/nic_helper'
22
21
  require 'fog/proxmox/helpers/disk_helper'
23
- require 'foreman_fog_proxmox/semver'
24
22
  require 'foreman_fog_proxmox/value'
25
23
 
26
24
  module ForemanFogProxmox
@@ -28,6 +26,18 @@ module ForemanFogProxmox
28
26
  include ProxmoxVmHelper
29
27
  include ProxmoxServerHelper
30
28
  include ProxmoxContainerHelper
29
+ include ProxmoxConnection
30
+ include ProxmoxTokenExpiration
31
+ include ProxmoxVmNew
32
+ include ProxmoxVmCommands
33
+ include ProxmoxVmQueries
34
+ include ProxmoxComputeAttributes
35
+ include ProxmoxVolumes
36
+ include ProxmoxInterfaces
37
+ include ProxmoxImages
38
+ include ProxmoxOperatingSystems
39
+ include ProxmoxVersion
40
+ include ProxmoxConsole
31
41
  validates :url, :format => { :with => URI::DEFAULT_PARSER.make_regexp }, :presence => true
32
42
  validates :user, :format => { :with => /(\w+)[@]{1}(\w+)/ }, :presence => true
33
43
  validates :password, :presence => true
@@ -36,12 +46,12 @@ module ForemanFogProxmox
36
46
 
37
47
  def provided_attributes
38
48
  super.merge(
39
- :mac => :mac
49
+ :mac => :mac
40
50
  )
41
51
  end
42
-
52
+
43
53
  def self.provider_friendly_name
44
- "Proxmox"
54
+ 'Proxmox'
45
55
  end
46
56
 
47
57
  def capabilities
@@ -52,417 +62,62 @@ module ForemanFogProxmox
52
62
  ComputeResource.model_name
53
63
  end
54
64
 
55
- def credentials_valid?
56
- errors[:url].empty? && errors[:user].empty? && errors[:user].include?('@') && errors[:password].empty? && errors[:node_id].empty?
57
- end
58
-
59
- def version_suitable?
60
- logger.debug(_("Proxmox compute resource version is %{version}") % { version: version })
61
- raise ::Foreman::Exception.new(_("Proxmox version %{version} is not semver suitable") % { version: version }) unless ForemanFogProxmox::Semver.is_semver?(version)
62
- ForemanFogProxmox::Semver.to_semver(version) >= ForemanFogProxmox::Semver.to_semver("5.3.0") && ForemanFogProxmox::Semver.to_semver(version) < ForemanFogProxmox::Semver.to_semver("5.5.0")
63
- end
64
-
65
- def test_connection(options = {})
66
- super
67
- credentials_valid?
68
- version_suitable?
69
- rescue => e
70
- errors[:base] << e.message
71
- if e.message.include?('SSL')
72
- errors[:ssl_certs] << e.message
73
- else
74
- errors[:url] << e.message
75
- end
76
- end
77
-
78
- def nodes
79
- nodes = client.nodes.all if client
80
- nodes.sort_by(&:node) if nodes
81
- end
82
-
83
- def pools
84
- pools = identity_client.pools.all
85
- pools.sort_by(&:poolid)
86
- end
87
-
88
- def storages(type = 'images')
89
- storages = node.storages.list_by_content_type type
90
- storages.sort_by(&:storage)
91
- end
92
-
93
- def images_by_storage(type = 'iso', storage_id)
94
- storage = node.storages.get storage_id if storage_id
95
- storage.volumes.list_by_content_type(type).sort_by(&:volid) if storage
96
- end
97
-
98
65
  def associated_host(vm)
99
66
  associate_by('mac', vm.mac)
100
67
  end
101
68
 
102
- def bridges
103
- node = network_client.nodes.get node_id
104
- bridges = node.networks.all(type: 'any_bridge')
105
- bridges.sort_by(&:iface)
106
- end
107
-
108
- def available_images
109
- templates.collect { |template| OpenStruct.new(id: template.vmid) }
110
- end
111
-
112
- def templates
113
- storage = storages.first
114
- images = storage.volumes.list_by_content_type('images')
115
- images.select { |image| image.templated? }
116
- end
117
-
118
- def template(vmid)
119
- find_vm_by_uuid(vmid)
120
- end
121
-
122
- def host_compute_attrs(host)
123
- super.tap do |attrs|
124
- ostype = host.compute_attributes['config_attributes']['ostype']
125
- type = host.compute_attributes['type']
126
- case type
127
- when 'lxc'
128
- host.compute_attributes['config_attributes'].store('hostname',host.name)
129
- when 'qemu'
130
- raise ::Foreman::Exception.new(_("Operating system family %{type} is not consistent with %{ostype}") % { type: host.operatingsystem.type, ostype: ostype }) unless compute_os_types(host).include?(ostype)
131
- end
132
- end
133
- end
134
-
135
- def host_interfaces_attrs(host)
136
- host.interfaces.select(&:physical?).each.with_index.reduce({}) do |hash, (nic, index)|
137
- # Set default interface identifier to net[n]
138
- nic.identifier = "net%{index}" % {index: index} if nic.identifier.empty?
139
- raise ::Foreman::Exception.new _("Invalid identifier interface[%{index}]. Must be net[n] with n integer >= 0" % { index: index }) unless Fog::Proxmox::NicHelper.nic?(nic.identifier)
140
- # Set default container interface name to eth[n]
141
- container = host.compute_attributes['type'] == 'lxc'
142
- nic.compute_attributes['name'] = "eth%{index}" % {index: index} if container && nic.compute_attributes['name'].empty?
143
- raise ::Foreman::Exception.new _("Invalid name interface[%{index}]. Must be eth[n] with n integer >= 0" % { index: index }) if container && !/^(eth)(\d+)$/.match?(nic.compute_attributes['name'])
144
- nic_compute_attributes = nic.compute_attributes.merge(id: nic.identifier)
145
- mac = nic.mac
146
- mac = nic.attributes['mac'] unless mac
147
- nic_compute_attributes.store(:macaddr, mac) if (mac && !mac.empty?)
148
- interface_compute_attributes = host.compute_attributes['interfaces_attributes'].select { |_k,v| v['id'] == nic.identifier }
149
- nic_compute_attributes.store(:_delete, interface_compute_attributes[interface_compute_attributes.keys[0]]['_delete']) unless interface_compute_attributes.empty?
150
- nic_compute_attributes.store(:ip, nic.ip) if (nic.ip && !nic.ip.empty?)
151
- nic_compute_attributes.store(:ip6, nic.ip6) if (nic.ip6 && !nic.ip6.empty?)
152
- hash.merge(index.to_s => nic_compute_attributes)
153
- end
154
- end
155
-
156
- def new_volume(attr = {})
157
- type = attr['type']
158
- type = 'qemu' unless type
159
- case type
160
- when 'lxc'
161
- return new_volume_server(attr)
162
- when 'qemu'
163
- return new_volume_container(attr)
164
- end
165
- end
166
-
167
- def new_volume_server(attr = {})
168
- opts = volume_server_defaults.merge(attr.to_h).deep_symbolize_keys
169
- opts[:size] = opts[:size].to_s
170
- Fog::Proxmox::Compute::Disk.new(opts)
171
- end
172
-
173
- def new_volume_container(attr = {})
174
- opts = volume_container_defaults.merge(attr.to_h).deep_symbolize_keys
175
- opts[:size] = opts[:size].to_s
176
- Fog::Proxmox::Compute::Disk.new(opts)
177
- end
178
-
179
- def new_interface(attr = {})
180
- type = attr['type']
181
- type = 'qemu' unless type
182
- case type
183
- when 'lxc'
184
- return new_container_interface(attr)
185
- when 'qemu'
186
- return new_server_interface(attr)
187
- end
188
- end
189
-
190
- def new_server_interface(attr = {})
191
- logger.debug("new_server_interface")
192
- opts = interface_server_defaults.merge(attr.to_h).deep_symbolize_keys
193
- Fog::Proxmox::Compute::Interface.new(opts)
194
- end
195
-
196
- def new_container_interface(attr = {})
197
- logger.debug("new_container_interface")
198
- opts = interface_container_defaults.merge(attr.to_h).deep_symbolize_keys
199
- Fog::Proxmox::Compute::Interface.new(opts)
200
- end
201
-
202
- def vm_compute_attributes(vm)
203
- vm_attrs = {}
204
- if vm.respond_to?(:config)
205
- vm_attrs = vm_attrs.merge(vmid: vm.identity, node_id: vm.node_id, type: vm.type)
206
- if vm.config.respond_to?(:disks)
207
- vm_attrs[:volumes_attributes] = Hash[vm.config.disks.each_with_index.map { |disk, idx| [idx.to_s, disk.attributes] }]
208
- end
209
- if vm.config.respond_to?(:interfaces)
210
- vm_attrs[:interfaces_attributes] = Hash[vm.config.interfaces.each_with_index.map { |interface, idx| [idx.to_s, interface.attributes] }]
211
- end
212
- vm_attrs[:config_attributes] = vm.config.attributes.reject { |key,value| [:disks, :interfaces, :vmid, :node_id, :node, :type].include?(key) || !vm.config.respond_to?(key) || ForemanFogProxmox::Value.empty?(value.to_s) || Fog::Proxmox::DiskHelper.disk?(key.to_s) || Fog::Proxmox::NicHelper.nic?(key.to_s) }
213
- end
214
- vm_attrs
215
- end
216
-
217
- def vms(opts = {})
218
- node
219
- end
220
-
221
- def new_vm(new_attr = {})
222
- new_attr = ActiveSupport::HashWithIndifferentAccess.new(new_attr)
223
- type = new_attr['type']
224
- type = 'qemu' unless type
225
- case type
226
- when 'lxc'
227
- vm = new_container_vm(new_attr)
228
- when 'qemu'
229
- vm = new_server_vm(new_attr)
230
- end
231
- logger.debug(_("new_vm() vm.config=%{config}") % { config: vm.config.inspect })
232
- vm
233
- end
234
-
235
- def new_container_vm(new_attr = {})
236
- options = new_attr
237
- options = options.merge(node_id: node_id).merge(type: 'lxc').merge(vmid: next_vmid)
238
- options= vm_container_instance_defaults.merge(options) if new_attr.empty?
239
- vm = node.containers.new(parse_container_vm(options).deep_symbolize_keys)
240
- logger.debug(_("new_container_vm() vm.config=%{config}") % { config: vm.config.inspect })
241
- vm
242
- end
243
-
244
- def new_server_vm(new_attr = {})
245
- options = new_attr
246
- options = options.merge(node_id: node_id).merge(type: 'qemu').merge(vmid: next_vmid)
247
- options = vm_server_instance_defaults.merge(options) if new_attr.empty?
248
- vm = node.servers.new(parse_server_vm(options).deep_symbolize_keys)
249
- logger.debug(_("new_server_vm() vm.config=%{config}") % { config: vm.config.inspect })
250
- vm
251
- end
252
-
253
- def create_vm(args = {})
254
- vmid = args[:vmid].to_i
255
- type = args[:type]
256
- raise ::Foreman::Exception.new N_("invalid vmid=%{vmid}") % { vmid: vmid } unless node.servers.id_valid?(vmid)
257
- image_id = args[:image_id]
258
- if image_id
259
- logger.debug(_("create_vm(): clone %{image_id} in %{vmid}") % { image_id: image_id, vmid: vmid })
260
- image = node.servers.get image_id
261
- image.clone(vmid)
262
- clone = node.servers.get vmid
263
- clone.update(name: args[:name])
264
- else
265
- convert_sizes(args)
266
- remove_deletes(args)
267
- case type
268
- when 'qemu'
269
- vm = node.servers.create(parse_server_vm(args))
270
- when 'lxc'
271
- hash = parse_container_vm(args)
272
- hash = hash.merge(vmid: vmid)
273
- vm = node.containers.create(hash.reject { |key,_value| %w[ostemplate_storage ostemplate_file].include? key })
274
- end
275
- end
276
- rescue => e
277
- logger.warn(_("failed to create vm: %{e}") % { e: e })
278
- destroy_vm vm.id if vm
279
- raise e
280
- end
281
-
282
- def find_vm_by_uuid(uuid)
283
- begin
284
- vm = node.servers.get(uuid)
285
- rescue Fog::Errors::NotFound
286
- vm = nil
287
- rescue Fog::Errors::Error => e
288
- Foreman::Logging.exception(_("Failed retrieving proxmox server vm by vmid=%{uuid}") % { vmid: uuid }, e)
289
- raise(ActiveRecord::RecordNotFound)
290
- end
291
- begin
292
- vm = node.containers.get(uuid) unless vm
293
- rescue Fog::Errors::NotFound
294
- vm = nil
295
- rescue Fog::Errors::Error => e
296
- Foreman::Logging.exception(_("Failed retrieving proxmox container vm by vmid=%{uuid}") % { vmid: uuid }, e)
297
- raise(ActiveRecord::RecordNotFound)
298
- end
299
- vm
300
- end
301
-
302
- def supports_update?
303
- true
304
- end
305
-
306
- def update_required?(old_attrs, new_attrs)
307
- return true if super(old_attrs, new_attrs)
308
-
309
- new_attrs[:interfaces_attributes].each do |key, interface|
310
- return true if (interface[:id].blank? || interface[:_delete] == '1') && key != 'new_interfaces' #ignore the template
311
- end if new_attrs[:interfaces_attributes]
312
-
313
- new_attrs[:volumes_attributes].each do |key, volume|
314
- return true if (volume[:id].blank? || volume[:_delete] == '1') && key != 'new_volumes' #ignore the template
315
- end if new_attrs[:volumes_attributes]
316
-
317
- false
318
- end
319
-
320
- def editable_network_interfaces?
321
- true
322
- end
323
-
324
- def user_data_supported?
325
- true
326
- end
327
-
328
- def image_exists?(image)
329
- !find_vm_by_uuid(image).nil?
330
- end
331
-
332
- def save_volumes(vm, volumes_attributes)
333
- if volumes_attributes
334
- volumes_attributes.each_value do |volume_attributes|
335
- id = volume_attributes['id']
336
- disk = vm.config.disks.get(id)
337
- delete = volume_attributes['_delete']
338
- if disk
339
- if delete == '1'
340
- vm.detach(id)
341
- device = Fog::Proxmox::DiskHelper.extract_device(id)
342
- vm.detach('unused' + device.to_s)
343
- else
344
- diff_size = volume_attributes['size'].to_i - disk.size
345
- raise ::Foreman::Exception.new(_("Unable to shrink %{id} size. Proxmox allows only increasing size.") % { id: id }) unless diff_size >= 0
346
- if diff_size > 0
347
- extension = '+' + (diff_size / GIGA).to_s + 'G'
348
- vm.extend(id,extension)
349
- elsif disk.storage != volume_attributes['storage']
350
- vm.move(id,volume_attributes['storage'])
351
- end
352
- end
353
- else
354
- options = {}
355
- options.store(:mp, volume_attributes['mp']) if vm.container?
356
- disk_attributes = { id: id, storage: volume_attributes['storage'], size: (volume_attributes['size'].to_i / GIGA).to_s }
357
- vm.attach(disk_attributes, options) unless delete == '1'
358
- end
359
- end
360
- end
361
- end
362
-
363
- def save_vm(uuid, new_attributes)
364
- vm = find_vm_by_uuid(uuid)
365
- templated = new_attributes['templated']
366
- if (templated == '1' && !vm.templated?)
367
- vm.create_template
368
- else
369
- volumes_attributes = new_attributes['volumes_attributes']
370
- save_volumes(vm, volumes_attributes)
371
- parsed_attr = vm.container? ? parse_container_vm(new_attributes.merge(type: vm.type)) : parse_server_vm(new_attributes.merge(type: vm.type))
372
- config_attributes = parsed_attr.reject { |key,_value| [:templated,:ostemplate,:ostemplate_file,:ostemplate_storage,:volumes_attributes].include? key.to_sym }
373
- config_attributes = config_attributes.reject { |_key,value| ForemanFogProxmox::Value.empty?(value) }
374
- cdrom_attributes = parsed_attr.select { |_key,value| Fog::Proxmox::DiskHelper.cdrom?(value.to_s) }
375
- config_attributes = config_attributes.reject { |key,_value| Fog::Proxmox::DiskHelper.disk?(key) }
376
- vm.update(config_attributes.merge(cdrom_attributes))
377
- end
378
- vm = find_vm_by_uuid(uuid)
379
- end
380
-
381
- def next_vmid
382
- node.servers.next_id
383
- end
384
-
385
- def node_id
386
- self.attrs[:node_id]
69
+ def node_id
70
+ attrs[:node_id]
387
71
  end
388
72
 
389
73
  def node_id=(value)
390
- self.attrs[:node_id] = value
74
+ attrs[:node_id] = value
391
75
  end
392
76
 
393
77
  def node
394
78
  client.nodes.get node_id
395
79
  end
396
80
 
397
- def ssl_certs
398
- self.attrs[:ssl_certs]
81
+ def ssl_certs
82
+ attrs[:ssl_certs]
399
83
  end
400
84
 
401
85
  def ssl_certs=(value)
402
- self.attrs[:ssl_certs] = value
86
+ attrs[:ssl_certs] = value
403
87
  end
404
88
 
405
89
  def certs_to_store
406
90
  return if ssl_certs.blank?
91
+
407
92
  store = OpenSSL::X509::Store.new
408
93
  ssl_certs.split(/(?=-----BEGIN)/).each do |cert|
409
94
  x509_cert = OpenSSL::X509::Certificate.new cert
410
95
  store.add_cert x509_cert
411
96
  end
412
97
  store
413
- rescue => e
98
+ rescue StandardError => e
414
99
  logger.error(e)
415
- raise ::Foreman::Exception.new N_("Unable to store X509 certificates")
100
+ raise ::Foreman::Exception, N_('Unable to store X509 certificates')
416
101
  end
417
102
 
418
103
  def ssl_verify_peer
419
- self.attrs[:ssl_verify_peer].blank? ? false : Foreman::Cast.to_bool(self.attrs[:ssl_verify_peer])
104
+ attrs[:ssl_verify_peer].blank? ? false : Foreman::Cast.to_bool(attrs[:ssl_verify_peer])
420
105
  end
421
106
 
422
107
  def ssl_verify_peer=(value)
423
- self.attrs[:ssl_verify_peer] = value
108
+ attrs[:ssl_verify_peer] = value
424
109
  end
425
110
 
426
- def connection_options
427
- opts = http_proxy ? {proxy: http_proxy.full_url} : {disable_proxy: 1}
428
- opts.store(:ssl_verify_peer, ssl_verify_peer)
429
- opts.store(:ssl_cert_store, certs_to_store) if Foreman::Cast.to_bool(ssl_verify_peer)
430
- opts
111
+ def renew
112
+ attrs[:renew].blank? ? false : Foreman::Cast.to_bool(attrs[:renew])
431
113
  end
432
114
 
433
- def console(uuid)
434
- vm = find_vm_by_uuid(uuid)
435
- options = {}
436
- if vm.container?
437
- type_console = 'vnc'
438
- options.store(:console, type_console)
439
- else
440
- type_console = vm.config.type_console
441
- end
442
- options.store(:websocket, 1) if type_console == 'vnc'
443
- begin
444
- vnc_console = vm.start_console(options)
445
- WsProxy.start(:host => host, :host_port => vnc_console['port'], :password => vnc_console['ticket']).merge(:name => vm.name, :type => type_console)
446
- rescue => e
447
- logger.error(e)
448
- raise ::Foreman::Exception.new(_("%s console is not supported at this time") % type_console)
449
- end
450
- end
451
-
452
- def version
453
- v = identity_client.read_version
454
- "#{v['version']}.#{v['release']}"
115
+ def renew=(value)
116
+ attrs[:renew] = value
455
117
  end
456
118
 
457
119
  private
458
120
 
459
- def fog_credentials
460
- { pve_url: url,
461
- pve_username: user,
462
- pve_password: password,
463
- connection_options: connection_options }
464
- end
465
-
466
121
  def client
467
122
  @client ||= ::Fog::Proxmox::Compute.new(fog_credentials)
468
123
  end
@@ -475,99 +130,8 @@ module ForemanFogProxmox
475
130
  @network_client ||= ::Fog::Proxmox::Network.new(fog_credentials)
476
131
  end
477
132
 
478
- def disconnect
479
- client.terminate if @client
480
- @client = nil
481
- identity_client.terminate if @identity_client
482
- @identity_client = nil
483
- network_client.terminate if @network_client
484
- @network_client = nil
485
- end
486
-
487
- def vm_server_instance_defaults
488
- ActiveSupport::HashWithIndifferentAccess.new(
489
- name: "foreman_#{Time.now.to_i}",
490
- vmid: next_vmid,
491
- type: 'qemu',
492
- node_id: node_id,
493
- cores: 1,
494
- sockets: 1,
495
- kvm: 0,
496
- vga: 'std',
497
- memory: 512 * MEGA,
498
- ostype: 'l26',
499
- keyboard: 'en-us',
500
- cpu: 'kvm64',
501
- scsihw: 'virtio-scsi-pci',
502
- ide2: "none,media=cdrom",
503
- templated: 0).merge(Fog::Proxmox::DiskHelper.flatten(volume_server_defaults)).merge(Fog::Proxmox::DiskHelper.flatten(volume_container_defaults)).merge(Fog::Proxmox::NicHelper.flatten(interface_defaults))
504
- end
505
-
506
- def vm_container_instance_defaults
507
- ActiveSupport::HashWithIndifferentAccess.new(
508
- name: "foreman_#{Time.now.to_i}",
509
- vmid: next_vmid,
510
- type: 'lxc',
511
- node_id: node_id,
512
- memory: 512 * MEGA,
513
- templated: 0).merge(Fog::Proxmox::DiskHelper.flatten(volume_container_defaults)).merge(Fog::Proxmox::DiskHelper.flatten(volume_server_defaults)).merge(Fog::Proxmox::NicHelper.flatten(interface_defaults))
514
- end
515
-
516
- def vm_instance_defaults
517
- super.merge(vmid: next_vmid, node_id: node_id)
518
- end
519
-
520
- def volume_server_defaults(controller = 'scsi', device = 0)
521
- id = "#{controller}#{device}"
522
- { id: id, storage: storages.first.identity.to_s, size: (8 * GIGA), options: { cache: 'none' } }
523
- end
524
-
525
- def volume_container_defaults(id='rootfs')
526
- { id: id, storage: storages.first.identity.to_s, size: (8 * GIGA), options: { } }
527
- end
528
-
529
- def interface_defaults(id = 'net0')
530
- { id: id, model: 'virtio', name: 'eth0', bridge: bridges.first.identity.to_s }
531
- end
532
-
533
- def interface_server_defaults(id = 'net0')
534
- { id: id, model: 'virtio', bridge: bridges.first.identity.to_s }
535
- end
536
-
537
- def interface_container_defaults(id = 'net0')
538
- { id: id, name: 'eth0', bridge: bridges.first.identity.to_s }
539
- end
540
-
541
- def compute_os_types(host)
542
- os_linux_types_mapping(host).empty? ? os_windows_types_mapping(host) : os_linux_types_mapping(host)
543
- end
544
-
545
- def available_operating_systems
546
- operating_systems = %w[other solaris]
547
- operating_systems += available_linux_operating_systems
548
- operating_systems += available_windows_operating_systems
549
- operating_systems
550
- end
551
-
552
- def available_linux_operating_systems
553
- %w[l24 l26 debian ubuntu centos fedora opensuse archlinux gentoo alpine]
554
- end
555
-
556
- def available_windows_operating_systems
557
- %w[wxp w2k w2k3 w2k8 wvista win7 win8 win10]
558
- end
559
-
560
- def os_linux_types_mapping(host)
561
- %w[Debian Redhat Suse Altlinux Archlinux CoreOs Gentoo].include?(host.operatingsystem.type) ? available_linux_operating_systems : []
562
- end
563
-
564
- def os_windows_types_mapping(host)
565
- %w[Windows].include?(host.operatingsystem.type) ? available_windows_operating_systems : []
566
- end
567
-
568
133
  def host
569
134
  URI.parse(url).host
570
135
  end
571
-
572
136
  end
573
137
  end