foreman_hyperv 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/javascripts/foreman_hyperv/compute_resource_base.js +0 -17
- data/app/helpers/foreman_hyperv/compute_resources_vms_helper.rb +19 -1
- data/app/models/concerns/fog_extensions/hyperv/compute.rb +2 -0
- data/app/models/concerns/fog_extensions/hyperv/hard_drive.rb +4 -2
- data/app/models/concerns/fog_extensions/hyperv/network_adapter.rb +33 -29
- data/app/models/concerns/fog_extensions/hyperv/server.rb +37 -17
- data/app/models/concerns/foreman_hyperv/host_managed_extensions.rb +3 -4
- data/app/models/foreman_hyperv/hyperv.rb +124 -66
- data/app/views/compute_resources_vms/form/hyperv/_base.html.erb +19 -29
- data/app/views/compute_resources_vms/form/hyperv/_network.html.erb +16 -16
- data/app/views/compute_resources_vms/form/hyperv/_volume.html.erb +1 -1
- data/lib/foreman_hyperv/version.rb +1 -1
- metadata +32 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 156c82d3cc4630c1d222fc97370cef6b5f3128da1d97732dcef072f8b4adbbe3
|
|
4
|
+
data.tar.gz: d812c0f6a6785879bbe4cacff1f943237b24951ea8b5b5f2e2add668d2480b58
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 89a21ca4968ec5adbc536b7cffde5e2619f4e54f704a259e52ec812ccb25271be31674c5bd0f6f154752c1a80d8b2eef836f497fe838781bd6f923ce1e8aa242
|
|
7
|
+
data.tar.gz: 16c7a09381db0854437d1620d708eabd7415459fc644577e508b45e94cd51e3c5b8bcd722eafeb049140615f15ea54fedbbf80e2a604dab17ecf82c4ea9395e2
|
|
@@ -1,20 +1,3 @@
|
|
|
1
|
-
$(document).on('ContentLoad', function() { tfm.numFields.initAll(); });
|
|
2
|
-
|
|
3
|
-
function hypervGenerationChange(item) {
|
|
4
|
-
var toIter = ['#host_compute_attributes_secure_boot_enabled', '#compute_attribute_vm_attrs_secure_boot_enabled'];
|
|
5
|
-
gen = $(item).val();
|
|
6
|
-
|
|
7
|
-
if (gen == 'BIOS') {
|
|
8
|
-
for (var i = 0; i < toIter.length; ++i) {
|
|
9
|
-
$(toIter[i]).attr('disabled', true);
|
|
10
|
-
}
|
|
11
|
-
} else {
|
|
12
|
-
for (var i = 0; i < toIter.length; ++i) {
|
|
13
|
-
$(toIter[i]).removeAttr('disabled');
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
1
|
function hypervDynamicMemoryChange(item) {
|
|
19
2
|
var toIter = [
|
|
20
3
|
'#host_compute_attributes_memory_maximum',
|
|
@@ -1,17 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ForemanHyperv
|
|
2
4
|
module ComputeResourcesVmsHelper
|
|
3
5
|
def hyperv_networks(compute_resource)
|
|
4
6
|
compute_resource.switches(nil).map do |sw|
|
|
5
|
-
[
|
|
7
|
+
[sw.id, "#{sw.name}#{" (#{sw.switch_type})" if sw.switch_type}"]
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def hyperv_boot_devices
|
|
12
|
+
devices = Fog::Hyperv::BOOT_DEVICE_ENUM_VALUES.dup
|
|
13
|
+
# devices.delete :Floppy if generation == :UEFI
|
|
14
|
+
devices.delete :IDE
|
|
15
|
+
devices.delete :LegacyNetworkAdapter
|
|
16
|
+
devices.map do |dev|
|
|
17
|
+
name = dev.to_s
|
|
18
|
+
name = 'Network Adapter' if dev == :NetworkAdapter
|
|
19
|
+
name = 'DVD' if dev == :CD
|
|
20
|
+
name = 'Floppy (Only for BIOS)' if dev == :Floppy
|
|
21
|
+
[dev, name]
|
|
6
22
|
end
|
|
7
23
|
end
|
|
8
24
|
|
|
9
25
|
def hyperv_generations
|
|
10
26
|
Fog::Hyperv::Compute::Server::VM_GENERATION_VALUES.map { |gen, num| [gen, "Generation #{num} (#{gen})"] }
|
|
11
27
|
end
|
|
28
|
+
|
|
12
29
|
def hyperv_vlan_modes
|
|
13
30
|
Fog::Hyperv::Compute::NetworkAdapterVlan::VLAN_OPERATION_MODE.map { |mode| [mode, mode] }
|
|
14
31
|
end
|
|
32
|
+
|
|
15
33
|
def hyperv_private_vlan_modes
|
|
16
34
|
Fog::Hyperv::Compute::NetworkAdapterVlan::PRIVATE_VLAN_MODE.reject { |mode| mode == :Unknown }.map { |mode| [mode, mode] }
|
|
17
35
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module FogExtensions
|
|
2
4
|
module Hyperv
|
|
3
5
|
module HardDrive
|
|
@@ -27,8 +29,8 @@ module FogExtensions
|
|
|
27
29
|
.slice(:id)
|
|
28
30
|
.merge(
|
|
29
31
|
{
|
|
30
|
-
basename
|
|
31
|
-
size_bytes:
|
|
32
|
+
basename: basename,
|
|
33
|
+
size_bytes: size_bytes
|
|
32
34
|
}.compact
|
|
33
35
|
)
|
|
34
36
|
end
|
|
@@ -7,16 +7,17 @@ module FogExtensions
|
|
|
7
7
|
|
|
8
8
|
def mac
|
|
9
9
|
return unless mac_address
|
|
10
|
-
return if mac_address.to_i(16)
|
|
10
|
+
return if mac_address.to_i(16).zero?
|
|
11
11
|
|
|
12
12
|
# Downcase and split every 2 chars, join with :
|
|
13
|
-
mac_address.downcase.scan(
|
|
13
|
+
mac_address.downcase.scan(/.{2}/).join(':')
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def mac=(m)
|
|
17
17
|
mac_address = m&.upcase&.delete(':')
|
|
18
18
|
mac_address = Fog::Hyperv::Compute::NetworkAdapter::NIC_FALLBACK_MAC if mac_address.nil? || mac_address.blank?
|
|
19
|
-
|
|
19
|
+
mac_address.to_i(16)
|
|
20
|
+
0
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
# VLAN settings
|
|
@@ -24,6 +25,7 @@ module FogExtensions
|
|
|
24
25
|
def vlan_operation_mode
|
|
25
26
|
vlan_setting.operation_mode
|
|
26
27
|
end
|
|
28
|
+
|
|
27
29
|
def vlan_operation_mode=(mode)
|
|
28
30
|
vlan_setting.operation_mode = mode
|
|
29
31
|
end
|
|
@@ -33,61 +35,60 @@ module FogExtensions
|
|
|
33
35
|
|
|
34
36
|
vlan_setting.private_vlan_mode
|
|
35
37
|
end
|
|
38
|
+
|
|
36
39
|
def vlan_private_mode=(mode)
|
|
37
40
|
vlan_setting.private_vlan_mode = mode
|
|
38
41
|
end
|
|
39
42
|
|
|
40
43
|
def access_vlan_id
|
|
41
|
-
return nil if vlan_setting.access_vlan_id.zero?
|
|
44
|
+
return nil if (vlan_setting.access_vlan_id || 0).zero?
|
|
42
45
|
|
|
43
46
|
vlan_setting.access_vlan_id
|
|
44
47
|
end
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
end
|
|
48
|
+
|
|
49
|
+
delegate :access_vlan_id=, to: :vlan_setting
|
|
48
50
|
|
|
49
51
|
def native_vlan_id
|
|
50
|
-
return nil if vlan_setting.native_vlan_id.zero?
|
|
52
|
+
return nil if (vlan_setting.native_vlan_id || 0).zero?
|
|
51
53
|
|
|
52
54
|
vlan_setting.native_vlan_id
|
|
53
55
|
end
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
end
|
|
56
|
+
|
|
57
|
+
delegate :native_vlan_id=, to: :vlan_setting
|
|
57
58
|
|
|
58
59
|
def allowed_vlan_ids
|
|
59
60
|
return nil unless vlan_setting.allowed_vlan_id_list&.any?
|
|
60
61
|
|
|
61
62
|
Fog::Hyperv::Compute::NetworkAdapterVlan.render_vlan_list vlan_setting.allowed_vlan_id_list
|
|
62
63
|
end
|
|
64
|
+
|
|
63
65
|
def allowed_vlan_ids=(ids)
|
|
64
66
|
ids ||= ''
|
|
65
67
|
vlan_setting.allowed_vlan_id_list = parse_vlan_list(ids)
|
|
66
68
|
end
|
|
67
69
|
|
|
68
70
|
def primary_vlan_id
|
|
69
|
-
return nil if vlan_setting.primary_vlan_id.zero?
|
|
71
|
+
return nil if (vlan_setting.primary_vlan_id || 0).zero?
|
|
70
72
|
|
|
71
73
|
vlan_setting.primary_vlan_id
|
|
72
74
|
end
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
end
|
|
75
|
+
|
|
76
|
+
delegate :primary_vlan_id=, to: :vlan_setting
|
|
76
77
|
|
|
77
78
|
def secondary_vlan_id
|
|
78
|
-
return nil if vlan_setting.secondary_vlan_id.zero?
|
|
79
|
+
return nil if (vlan_setting.secondary_vlan_id || 0).zero?
|
|
79
80
|
|
|
80
81
|
vlan_setting.secondary_vlan_id
|
|
81
82
|
end
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
end
|
|
83
|
+
|
|
84
|
+
delegate :secondary_vlan_id=, to: :vlan_setting
|
|
85
85
|
|
|
86
86
|
def secondary_vlan_ids
|
|
87
87
|
return nil unless vlan_setting.secondary_vlan_id_list&.any?
|
|
88
88
|
|
|
89
89
|
Fog::Hyperv::Compute::NetworkAdapterVlan.render_vlan_list vlan_setting.secondary_vlan_id_list
|
|
90
90
|
end
|
|
91
|
+
|
|
91
92
|
def secondary_vlan_ids=(ids)
|
|
92
93
|
ids ||= ''
|
|
93
94
|
vlan_setting.secondary_vlan_id_list = parse_vlan_list(ids)
|
|
@@ -100,17 +101,20 @@ module FogExtensions
|
|
|
100
101
|
:switch_id
|
|
101
102
|
)
|
|
102
103
|
.merge(
|
|
103
|
-
|
|
104
|
-
vlan_operation_mode
|
|
105
|
-
vlan_private_mode
|
|
106
|
-
access_vlan_id
|
|
107
|
-
native_vlan_id
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
104
|
+
vlan_setting.attributes.slice(
|
|
105
|
+
:vlan_operation_mode,
|
|
106
|
+
:vlan_private_mode,
|
|
107
|
+
:access_vlan_id,
|
|
108
|
+
:native_vlan_id,
|
|
109
|
+
:primary_vlan_id,
|
|
110
|
+
:secondary_vlan_id
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
.merge(
|
|
114
|
+
secondary_vlan_ids: secondary_vlan_ids,
|
|
115
|
+
allowed_vlan_ids: allowed_vlan_ids
|
|
113
116
|
)
|
|
117
|
+
.compact
|
|
114
118
|
end
|
|
115
119
|
|
|
116
120
|
private
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module FogExtensions
|
|
2
4
|
module Hyperv
|
|
3
5
|
module Server
|
|
@@ -9,7 +11,7 @@ module FogExtensions
|
|
|
9
11
|
end
|
|
10
12
|
|
|
11
13
|
def folder_name
|
|
12
|
-
name.gsub(/[^0-9A-Za-z
|
|
14
|
+
name.gsub(/[^0-9A-Za-z.-]/, '_')
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
def mac
|
|
@@ -40,7 +42,20 @@ module FogExtensions
|
|
|
40
42
|
def cluster_name=(name)
|
|
41
43
|
@cluster = service.clusters.get(name)
|
|
42
44
|
end
|
|
43
|
-
|
|
45
|
+
|
|
46
|
+
def boot_device
|
|
47
|
+
:NetworkAdapter
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def foreman_firmware_type
|
|
51
|
+
return 'bios' if generation_num == 1
|
|
52
|
+
|
|
53
|
+
secure_boot_enabled ? 'uefi_secure_boot' : 'uefi'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def foreman_firmware
|
|
57
|
+
generation_num == 1 ? 'bios' : 'efi'
|
|
58
|
+
end
|
|
44
59
|
|
|
45
60
|
def vlan
|
|
46
61
|
nic = network_adapters.first
|
|
@@ -51,7 +66,7 @@ module FogExtensions
|
|
|
51
66
|
def vlan=(vlan)
|
|
52
67
|
logger.warn "using vlan=#{vlan.inspect} on Hyper-V VM, this can lead to unexpected results"
|
|
53
68
|
nic = network_adapters.first
|
|
54
|
-
if vlan.present? && vlan.to_i
|
|
69
|
+
if vlan.present? && vlan.to_i.positive?
|
|
55
70
|
nic.vlan_operation_mode = :Access if nic.vlan_operation_mode == :Untagged
|
|
56
71
|
case nic.vlan_operation_mode
|
|
57
72
|
when :Access
|
|
@@ -68,16 +83,15 @@ module FogExtensions
|
|
|
68
83
|
|
|
69
84
|
def secure_boot_enabled=(enabled)
|
|
70
85
|
return if generation != :UEFI
|
|
71
|
-
|
|
72
|
-
@secure_boot = enabled
|
|
73
86
|
return unless persisted?
|
|
74
87
|
|
|
75
88
|
firmware.secure_boot = enabled ? :On : :Off
|
|
89
|
+
firmware.save
|
|
76
90
|
end
|
|
77
91
|
|
|
78
92
|
def secure_boot_enabled
|
|
79
93
|
return false if generation != :UEFI
|
|
80
|
-
return
|
|
94
|
+
return unless persisted?
|
|
81
95
|
|
|
82
96
|
firmware.secure_boot == :On
|
|
83
97
|
end
|
|
@@ -103,29 +117,35 @@ module FogExtensions
|
|
|
103
117
|
match ||= fog_nics.detect { |fn| fn.mac == nic.mac }
|
|
104
118
|
# match ||= fog_nics.detect { |fn| fn.name == nic_attrs['name'].presence }
|
|
105
119
|
|
|
106
|
-
|
|
120
|
+
unless match
|
|
107
121
|
# Match on networking, limit potentials down to identical configuration and then pick the first
|
|
108
122
|
potential = fog_nics.select do |fn|
|
|
109
123
|
fn.switch_id == nic_attrs['switch_id'].presence || fn.switch_name == nic_attrs['switch_name'].presence
|
|
110
124
|
end
|
|
111
125
|
potential.select! { |fn| fn.vlan_operation_mode.to_s == nic_attrs['vlan_operation_mode'] }
|
|
112
|
-
|
|
126
|
+
case nic_attrs['vlan_operation_mode']
|
|
127
|
+
when 'Access'
|
|
113
128
|
potential.select! { |fn| fn.access_vlan_id.to_s == nic_attrs['access_vlan_id'] }
|
|
114
|
-
|
|
129
|
+
when 'Trunk'
|
|
115
130
|
potential.select! { |fn| fn.native_vlan_id.to_s == nic_attrs['native_vlan_id'] }
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
131
|
+
if nic_attrs['allowed_vlan_ids'].present?
|
|
132
|
+
potential.select! do |fn|
|
|
133
|
+
fn.allowed_vlan_ids.split(',').map(&:strip) == nic_attrs['allowed_vlan_ids'].split(',').map(&:strip)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
when 'Private'
|
|
119
137
|
potential.select! { |fn| fn.vlan_private_mode.to_s == nic_attrs['vlan_private_mode'] }
|
|
120
138
|
potential.select! { |fn| fn.primary_vlan_id.to_s == nic_attrs['primary_vlan_id'].to_s } \
|
|
121
139
|
if nic_attrs['primary_vlan_id'].present?
|
|
122
140
|
|
|
123
141
|
if nic_attrs['vlan_private_mode'] == 'Promiscuous'
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
142
|
+
if nic_attrs['secondary_vlan_ids'].present?
|
|
143
|
+
potential.select! do |fn|
|
|
144
|
+
fn.secondary_vlan_ids.split(',').map(&:strip) == nic_attrs['secondary_vlan_ids'].split(',').map(&:strip)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
elsif nic_attrs['secondary_vlan_id'].present?
|
|
148
|
+
potential.select! { |fn| fn.secondary_vlan_id.to_s == nic_attrs['secondary_vlan_id'].to_s }
|
|
129
149
|
end
|
|
130
150
|
end
|
|
131
151
|
|
|
@@ -16,9 +16,9 @@ module ForemanHyperv
|
|
|
16
16
|
|
|
17
17
|
begin
|
|
18
18
|
hyperv_sync_interfaces
|
|
19
|
-
rescue => e
|
|
19
|
+
rescue StandardError => e
|
|
20
20
|
failure _("Failed to update a compute %{compute_resource} instance %{name}: %{e}") %
|
|
21
|
-
{ compute_resource
|
|
21
|
+
{ compute_resource: compute_resource, name: name, e: e }, e
|
|
22
22
|
end
|
|
23
23
|
true
|
|
24
24
|
end
|
|
@@ -41,8 +41,7 @@ module ForemanHyperv
|
|
|
41
41
|
selected_nic = vm.select_nic(fog_nics, nic)
|
|
42
42
|
if selected_nic.nil?
|
|
43
43
|
logger.warn "Orchestration::Compute: Could not match network interface #{nic.inspect}"
|
|
44
|
-
raise ArgumentError,
|
|
45
|
-
_("Could not find virtual machine network interface matching %s") %
|
|
44
|
+
raise ArgumentError, _("Could not find virtual machine network interface matching %s") %
|
|
46
45
|
[nic.identifier, nic.ip, nic.name, nic.type].find(&:present?)
|
|
47
46
|
end
|
|
48
47
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ForemanHyperv
|
|
2
4
|
class Hyperv < ::ComputeResource
|
|
3
5
|
include ComputeResourceCaching
|
|
@@ -37,7 +39,7 @@ module ForemanHyperv
|
|
|
37
39
|
validate_connectivity(options)
|
|
38
40
|
end
|
|
39
41
|
|
|
40
|
-
def validate_connectivity(
|
|
42
|
+
def validate_connectivity(_options = {})
|
|
41
43
|
return unless connection_properties_valid?
|
|
42
44
|
return false if errors.any?
|
|
43
45
|
|
|
@@ -66,10 +68,6 @@ module ForemanHyperv
|
|
|
66
68
|
super.merge(mac: :mac)
|
|
67
69
|
end
|
|
68
70
|
|
|
69
|
-
def editable_network_interfaces?
|
|
70
|
-
true
|
|
71
|
-
end
|
|
72
|
-
|
|
73
71
|
# TODO
|
|
74
72
|
def max_cpu_count(host = nil)
|
|
75
73
|
(host || hypervisor).logical_processor_count
|
|
@@ -110,6 +108,10 @@ module ForemanHyperv
|
|
|
110
108
|
)
|
|
111
109
|
end
|
|
112
110
|
|
|
111
|
+
def associated_host(vm)
|
|
112
|
+
associate_by("mac", vm.network_adapters.map(&:mac))
|
|
113
|
+
end
|
|
114
|
+
|
|
113
115
|
delegate :servers, to: :client
|
|
114
116
|
|
|
115
117
|
def switches(host)
|
|
@@ -122,12 +124,16 @@ module ForemanHyperv
|
|
|
122
124
|
end
|
|
123
125
|
|
|
124
126
|
def new_vm(attr = {})
|
|
127
|
+
firmware_type = attr.delete(:firmware_type).to_s
|
|
128
|
+
attr.merge!(process_firmware_attributes(attr[:foreman_firmware], firmware_type)) #, attr[:provision_method]))
|
|
125
129
|
attr.delete :id
|
|
130
|
+
|
|
131
|
+
# logger.debug "New VM with arguments;\n#{attr}"
|
|
126
132
|
vm = super
|
|
127
133
|
iface_nested_attrs = nested_attributes_for :interfaces, attr[:interfaces_attributes]
|
|
128
134
|
vm.network_adapters = iface_nested_attrs.map do |attr|
|
|
129
135
|
attr.delete :id
|
|
130
|
-
Fog::Hyperv::Compute::NetworkAdapter.new(service: vm.service, vm:).tap do |nic|
|
|
136
|
+
Fog::Hyperv::Compute::NetworkAdapter.new(service: vm.service, vm: vm).tap do |nic|
|
|
131
137
|
attr.select { |_, v| v.present? }.each do |k, v|
|
|
132
138
|
nic.send(:"#{k}=", v)
|
|
133
139
|
end
|
|
@@ -136,7 +142,7 @@ module ForemanHyperv
|
|
|
136
142
|
volume_nested_attrs = nested_attributes_for :volumes, attr[:volumes_attributes]
|
|
137
143
|
vm.hard_drives = volume_nested_attrs.map do |attr|
|
|
138
144
|
attr.delete :id
|
|
139
|
-
Fog::Hyperv::Compute::HardDrive.new(service: vm.service, vm:).tap do |hdd|
|
|
145
|
+
Fog::Hyperv::Compute::HardDrive.new(service: vm.service, vm: vm).tap do |hdd|
|
|
140
146
|
attr.select { |_, v| v.present? }.each do |k, v|
|
|
141
147
|
hdd.send(:"#{k}=", v)
|
|
142
148
|
end
|
|
@@ -151,13 +157,17 @@ module ForemanHyperv
|
|
|
151
157
|
attr.delete :computer_name if attr[:computer_name].blank?
|
|
152
158
|
attr.delete :start
|
|
153
159
|
|
|
160
|
+
firmware_type = attr.delete(:firmware_type).to_s
|
|
161
|
+
attr.merge!(process_firmware_attributes(attr[:foreman_firmware], firmware_type)) #, attr[:provision_method]))
|
|
162
|
+
|
|
154
163
|
validate_vm(attr, new: true)
|
|
155
164
|
validate_interfaces(attr)
|
|
156
165
|
validate_volumes(attr)
|
|
157
166
|
|
|
167
|
+
# logger.debug "Creating VM with arguments; #{attr}"
|
|
158
168
|
vm = client.servers.new(
|
|
159
169
|
name: attr[:name],
|
|
160
|
-
computer_name: attr[:computer_name],
|
|
170
|
+
computer_name: attr[:computer_name].presence || hypervisor.name,
|
|
161
171
|
generation: attr[:generation],
|
|
162
172
|
dynamic_memory_enabled: Foreman::Cast.to_bool(attr[:dynamic_memory_enabled]),
|
|
163
173
|
memory_startup: attr[:memory_startup].to_i,
|
|
@@ -166,13 +176,20 @@ module ForemanHyperv
|
|
|
166
176
|
processor_count: attr[:processor_count].to_i,
|
|
167
177
|
notes: attr[:notes]
|
|
168
178
|
)
|
|
169
|
-
|
|
170
|
-
|
|
179
|
+
vm.create(
|
|
180
|
+
# TODO: should be :VHD if image build - when image build support exists
|
|
181
|
+
boot_device: attr[:boot_device].present? ? attr[:boot_device].to_sym : :NetworkAdapter,
|
|
182
|
+
path: hypervisor.virtual_machine_path
|
|
183
|
+
)
|
|
171
184
|
|
|
172
|
-
if vm.generation == :UEFI
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
185
|
+
if vm.generation == :UEFI
|
|
186
|
+
vm.secure_boot_enabled = attr[:secure_boot_enabled]
|
|
187
|
+
if attr[:tpm_enabled] == '1'
|
|
188
|
+
security = vm.security
|
|
189
|
+
security.change_key_protector :new
|
|
190
|
+
security.tpm_enabled = true
|
|
191
|
+
security.save
|
|
192
|
+
end
|
|
176
193
|
end
|
|
177
194
|
|
|
178
195
|
create_interfaces(vm, attr)
|
|
@@ -180,27 +197,26 @@ module ForemanHyperv
|
|
|
180
197
|
|
|
181
198
|
vm.start if attr[:start] == '1'
|
|
182
199
|
vm
|
|
183
|
-
rescue StandardError
|
|
184
|
-
if vm
|
|
200
|
+
rescue StandardError
|
|
201
|
+
if vm&.persisted?
|
|
185
202
|
vm.stop
|
|
186
203
|
vm.hard_drives.each { |hdd| hdd.destroy(underlying: true) }
|
|
187
|
-
vm.destroy
|
|
204
|
+
vm.destroy(vm.path.end_with?(vm.name))
|
|
188
205
|
end
|
|
189
206
|
|
|
190
|
-
raise
|
|
207
|
+
raise
|
|
191
208
|
end
|
|
192
209
|
|
|
193
210
|
def save_vm(uuid, web_attr)
|
|
194
211
|
attr = web_attr.deep_symbolize_keys
|
|
212
|
+
attr.delete :start
|
|
195
213
|
|
|
196
214
|
validate_vm(attr)
|
|
197
215
|
validate_interfaces(attr)
|
|
198
216
|
validate_volumes(attr)
|
|
199
217
|
|
|
200
|
-
attr.delete :start
|
|
201
|
-
|
|
202
218
|
vm = find_vm_by_uuid(uuid)
|
|
203
|
-
logger.debug "Updating VM #{vm} with arguments; #{attr}"
|
|
219
|
+
# logger.debug "Updating VM #{vm} with arguments; #{attr}"
|
|
204
220
|
|
|
205
221
|
vm.processor_count = attr[:processor_count].to_i
|
|
206
222
|
vm.notes = attr[:notes].presence
|
|
@@ -209,10 +225,19 @@ module ForemanHyperv
|
|
|
209
225
|
vm.memory_minimum = attr[:memory_minimum].to_i
|
|
210
226
|
vm.memory_maximum = attr[:memory_maximum].to_i
|
|
211
227
|
end
|
|
212
|
-
if vm.generation == :UEFI && attr[:
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
228
|
+
if vm.generation == :UEFI && attr[:tpm_enabled].present?
|
|
229
|
+
security = vm.security
|
|
230
|
+
security.tpm_enabled = attr[:tpm_enabled] == '1'
|
|
231
|
+
if security.tpm_enabled && security.key_protector.nil?
|
|
232
|
+
security.change_key_protector :new
|
|
233
|
+
end
|
|
234
|
+
security.save
|
|
235
|
+
end
|
|
236
|
+
if attr[:foreman_firmware].present?
|
|
237
|
+
firmware_type = attr.delete(:firmware_type).to_s
|
|
238
|
+
attr.merge!(process_firmware_attributes(attr[:foreman_firmware], firmware_type)) #, attr[:provision_method]))
|
|
239
|
+
|
|
240
|
+
vm.secure_boot_enabled = attr[:secure_boot_enabled]
|
|
216
241
|
end
|
|
217
242
|
|
|
218
243
|
update_interfaces(vm, attr)
|
|
@@ -227,35 +252,36 @@ module ForemanHyperv
|
|
|
227
252
|
vm.stop turn_off: true
|
|
228
253
|
vm.hard_drives.each { |hdd| hdd.destroy(underlying: true) }
|
|
229
254
|
# TODO: Remove the empty VM folder
|
|
230
|
-
vm.destroy
|
|
255
|
+
vm.destroy(vm.path.end_with?(vm.name))
|
|
231
256
|
rescue ActiveRecord::RecordNotFound, Fog::Errors::NotFound
|
|
232
257
|
# if the VM does not exists, we don't really care.
|
|
233
258
|
true
|
|
234
259
|
end
|
|
235
260
|
|
|
236
261
|
def update_required?(old_attrs, new_attrs)
|
|
237
|
-
new_attrs.deep_symbolize_keys[:volumes_attributes]&.
|
|
262
|
+
new_attrs.deep_symbolize_keys[:volumes_attributes]&.each_value do |hdd|
|
|
238
263
|
if hdd[:id].present? && hdd[:_delete] == '1'
|
|
239
|
-
Rails.logger.debug
|
|
264
|
+
Rails.logger.debug 'Scheduling compute instance update because a volume was removed'
|
|
240
265
|
return true
|
|
241
|
-
elsif
|
|
242
|
-
Rails.logger.debug
|
|
266
|
+
elsif hdd[:id].blank? && hdd[:_delete] != '1'
|
|
267
|
+
Rails.logger.debug 'Scheduling compute instance update because a new volume was added'
|
|
243
268
|
return true
|
|
244
269
|
end
|
|
245
270
|
end
|
|
246
|
-
new_attrs.deep_symbolize_keys[:interfaces_attributes]&.
|
|
271
|
+
new_attrs.deep_symbolize_keys[:interfaces_attributes]&.each_value do |iface|
|
|
247
272
|
if iface[:id].present? && iface[:_destroy] == '1'
|
|
248
|
-
Rails.logger.debug
|
|
273
|
+
Rails.logger.debug 'Scheduling compute instance update because an interface was removed'
|
|
249
274
|
return true
|
|
250
|
-
elsif
|
|
251
|
-
Rails.logger.debug
|
|
275
|
+
elsif iface[:id].blank? && iface[:_destroy] != '1'
|
|
276
|
+
Rails.logger.debug 'Scheduling compute instance update because a new interface was added'
|
|
252
277
|
return true
|
|
253
278
|
end
|
|
254
279
|
end
|
|
255
280
|
|
|
256
|
-
deep_update_required = proc do |old, new|
|
|
281
|
+
deep_update_required = proc do |path, old, new|
|
|
257
282
|
old.merge(new) do |k, old_v, new_v|
|
|
258
|
-
|
|
283
|
+
k_path = path + [k]
|
|
284
|
+
if %i[allowed_vlan_ids secondary_vlan_ids].include?(k)
|
|
259
285
|
tmp = Fog::Hyperv::Compute::NetworkAdapter.new
|
|
260
286
|
|
|
261
287
|
old_v = Fog::Hyperv::Compute::NetworkAdapterVlan.render_vlan_list(tmp.send(:parse_vlan_list, old_v.to_s))
|
|
@@ -263,15 +289,17 @@ module ForemanHyperv
|
|
|
263
289
|
end
|
|
264
290
|
|
|
265
291
|
if old_v.is_a?(Hash) && new_v.is_a?(Hash)
|
|
266
|
-
deep_update_required.call(old_v, new_v)
|
|
292
|
+
deep_update_required.call(k_path, old_v, new_v)
|
|
267
293
|
elsif old_v.to_s != new_v.to_s
|
|
268
|
-
Rails.logger.debug
|
|
294
|
+
Rails.logger.debug do
|
|
295
|
+
"Scheduling compute instance update because #{k_path.join('.')} changed it's value from '#{old_v}' (#{old_v.class}) to '#{new_v}' (#{new_v.class})"
|
|
296
|
+
end
|
|
269
297
|
return true
|
|
270
298
|
end
|
|
271
299
|
new_v
|
|
272
300
|
end
|
|
273
301
|
end
|
|
274
|
-
deep_update_required.call(old_attrs.deep_symbolize_keys, new_attrs.deep_symbolize_keys)
|
|
302
|
+
deep_update_required.call([], old_attrs.deep_symbolize_keys, new_attrs.deep_symbolize_keys)
|
|
275
303
|
|
|
276
304
|
false
|
|
277
305
|
end
|
|
@@ -293,8 +321,8 @@ module ForemanHyperv
|
|
|
293
321
|
basename = attr.delete(:basename) { 'Disk' }
|
|
294
322
|
size = attr.delete(:size)
|
|
295
323
|
|
|
296
|
-
vhd = client.vhds.new({ basename
|
|
297
|
-
Fog::Hyperv::Compute::HardDrive.new vhd
|
|
324
|
+
vhd = client.vhds.new({ basename: basename, size: size }.compact)
|
|
325
|
+
Fog::Hyperv::Compute::HardDrive.new vhd: vhd, **attr
|
|
298
326
|
end
|
|
299
327
|
|
|
300
328
|
def new_cdrom(attr = {})
|
|
@@ -303,13 +331,26 @@ module ForemanHyperv
|
|
|
303
331
|
|
|
304
332
|
def vm_instance_defaults
|
|
305
333
|
super.merge(
|
|
306
|
-
generation:
|
|
307
|
-
memory_startup:
|
|
334
|
+
generation: 2,
|
|
335
|
+
memory_startup: 1024.megabytes,
|
|
308
336
|
processor_count: 1,
|
|
309
|
-
interfaces:
|
|
337
|
+
interfaces: [new_interface]
|
|
310
338
|
)
|
|
311
339
|
end
|
|
312
340
|
|
|
341
|
+
def vm_compute_attributes(vm)
|
|
342
|
+
attr = super.slice(
|
|
343
|
+
:computer_name, :name, :generation,
|
|
344
|
+
:dynamic_memory_enabled,
|
|
345
|
+
:memory_maximum, :memory_minimum, :memory_startup,
|
|
346
|
+
:notes, :processor_count
|
|
347
|
+
)
|
|
348
|
+
attr[:foreman_firmware] = vm.foreman_firmware_type
|
|
349
|
+
attr[:tpm_enabled] = vm.tpm_enabled
|
|
350
|
+
|
|
351
|
+
attr
|
|
352
|
+
end
|
|
353
|
+
|
|
313
354
|
def set_vm_volumes_attributes(vm, vm_attrs)
|
|
314
355
|
volumes = vm.hard_drives || []
|
|
315
356
|
vm_attrs[:volumes_attributes] = volumes.each_with_index.to_h do |volume, index|
|
|
@@ -344,25 +385,30 @@ module ForemanHyperv
|
|
|
344
385
|
private
|
|
345
386
|
|
|
346
387
|
def _clusters
|
|
347
|
-
if client.respond_to?
|
|
348
|
-
return [] unless client.supports_clusters?
|
|
349
|
-
end
|
|
388
|
+
return [] if client.respond_to?(:supports_clusters?) && !client.supports_clusters?
|
|
350
389
|
|
|
351
390
|
client.clusters.all
|
|
352
|
-
rescue
|
|
391
|
+
rescue StandardError
|
|
353
392
|
[]
|
|
354
393
|
end
|
|
355
394
|
|
|
356
395
|
def validate_vm(attr, new: false)
|
|
357
396
|
# logger.debug "Validate VM #{attr.inspect}"
|
|
358
|
-
raise Foreman::Exception, 'VM lacks generation' if new &&
|
|
359
|
-
raise Foreman::Exception, 'VM lacks memory' unless attr[:memory_startup].to_i
|
|
360
|
-
raise Foreman::Exception, 'VM lacks CPUs' unless attr[:processor_count].to_i
|
|
397
|
+
raise Foreman::Exception, 'VM lacks generation' if new && attr[:generation].blank?
|
|
398
|
+
raise Foreman::Exception, 'VM lacks memory' unless attr[:memory_startup].to_i.positive?
|
|
399
|
+
raise Foreman::Exception, 'VM lacks CPUs' unless attr[:processor_count].to_i.positive?
|
|
361
400
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
401
|
+
return unless Foreman::Cast.to_bool(attr[:dynamic_memory_enabled])
|
|
402
|
+
raise Foreman::Exception, 'VM lacks memory minimum' unless attr[:memory_minimum].to_i.positive?
|
|
403
|
+
raise Foreman::Exception, 'VM lacks memory maximum' unless attr[:memory_maximum].to_i.positive?
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def generate_secure_boot_settings(firmware)
|
|
407
|
+
return {} unless firmware.to_s.include?('efi')
|
|
408
|
+
|
|
409
|
+
{
|
|
410
|
+
secure_boot_enabled: firmware.to_s.end_with?('secure_boot')
|
|
411
|
+
}
|
|
366
412
|
end
|
|
367
413
|
|
|
368
414
|
def validate_interfaces(attr)
|
|
@@ -373,18 +419,26 @@ module ForemanHyperv
|
|
|
373
419
|
compute = iface[:compute_attributes] || iface
|
|
374
420
|
case compute[:vlan_operation_mode].to_s
|
|
375
421
|
when 'Untagged'
|
|
422
|
+
# No VLAN settings to verify
|
|
376
423
|
when 'Access'
|
|
377
|
-
raise Foreman::Exception, 'Interface is missing access VLAN' unless compute[:access_vlan_id].to_i
|
|
424
|
+
raise Foreman::Exception, 'Interface is missing access VLAN' unless compute[:access_vlan_id].to_i.positive?
|
|
378
425
|
when 'Trunk'
|
|
379
|
-
raise Foreman::Exception, 'Interface is missing native VLAN' unless compute[:native_vlan_id].to_i
|
|
380
|
-
raise Foreman::Exception, 'Interface is missing allowed VLANs'
|
|
426
|
+
raise Foreman::Exception, 'Interface is missing native VLAN' unless compute[:native_vlan_id].to_i.positive?
|
|
427
|
+
raise Foreman::Exception, 'Interface is missing allowed VLANs' if compute[:allowed_vlan_ids].blank?
|
|
381
428
|
when 'Private'
|
|
382
|
-
raise Foreman::Exception, 'Interface is missing primary VLAN' unless compute[:primary_vlan_id].to_i
|
|
429
|
+
raise Foreman::Exception, 'Interface is missing primary VLAN' unless compute[:primary_vlan_id].to_i.positive?
|
|
430
|
+
|
|
383
431
|
case compute[:vlan_private_mode].to_s
|
|
384
432
|
when 'Promiscuous'
|
|
385
|
-
|
|
433
|
+
if compute[:secondary_vlan_ids].blank?
|
|
434
|
+
raise Foreman::Exception,
|
|
435
|
+
'Interface is missing secondary VLANs'
|
|
436
|
+
end
|
|
386
437
|
else
|
|
387
|
-
|
|
438
|
+
unless compute[:secondary_vlan_id].to_i.positive?
|
|
439
|
+
raise Foreman::Exception,
|
|
440
|
+
'Interface is missing secondary VLAN'
|
|
441
|
+
end
|
|
388
442
|
end
|
|
389
443
|
else
|
|
390
444
|
raise Foreman::Exception, 'Interface has unknown VLAN mode'
|
|
@@ -411,7 +465,9 @@ module ForemanHyperv
|
|
|
411
465
|
nic.save
|
|
412
466
|
end
|
|
413
467
|
|
|
414
|
-
|
|
468
|
+
unless vm.network_adapters.all(_return_fields: %i[dynamic_mac_address_enabled]).any?(&:dynamic_mac_address_enabled)
|
|
469
|
+
return
|
|
470
|
+
end
|
|
415
471
|
|
|
416
472
|
# Populate all non-populated MAC addresses
|
|
417
473
|
vm.start
|
|
@@ -456,11 +512,13 @@ module ForemanHyperv
|
|
|
456
512
|
volumes.reject! { |vol| vol[:_delete] == '1' }
|
|
457
513
|
# logger.debug "Validate Volume #{volumes.inspect}"
|
|
458
514
|
volumes.each do |vol|
|
|
459
|
-
raise Foreman::Exception, 'Volume lacks name'
|
|
515
|
+
raise Foreman::Exception, 'Volume lacks name' if vol[:basename].blank?
|
|
460
516
|
raise Foreman::Exception, 'Volume name should not include a file extension' if vol[:basename] =~ /\.vhd[sx]?$/
|
|
461
|
-
raise Foreman::Exception, 'Volume lacks size' unless vol[:size_bytes].to_i
|
|
517
|
+
raise Foreman::Exception, 'Volume lacks size' unless vol[:size_bytes].to_i.positive?
|
|
462
518
|
end
|
|
463
|
-
|
|
519
|
+
return unless volumes.group_by { |vol| vol[:basename].downcase }.any? { |_k, v| v.many? }
|
|
520
|
+
|
|
521
|
+
raise Foreman::Exception, 'Volume names need to be unique'
|
|
464
522
|
end
|
|
465
523
|
|
|
466
524
|
def create_volumes(vm, attr)
|
|
@@ -468,7 +526,7 @@ module ForemanHyperv
|
|
|
468
526
|
logger.debug "Creating volumes with: #{volumes}"
|
|
469
527
|
volumes.each do |vol|
|
|
470
528
|
vhd = vm.vhds.create basename: vol[:basename], size: vol[:size_bytes].to_i
|
|
471
|
-
vm.hard_drives.create vhd:
|
|
529
|
+
vm.hard_drives.create vhd: vhd
|
|
472
530
|
end
|
|
473
531
|
end
|
|
474
532
|
|
|
@@ -14,34 +14,12 @@
|
|
|
14
14
|
cluster_errors << ex
|
|
15
15
|
end
|
|
16
16
|
-%>
|
|
17
|
-
<% if clusters.any?
|
|
17
|
+
<% if clusters.any? -%>
|
|
18
18
|
<%= select_f f, :cluster_name, clusters, :to_s, :to_s, { include_blank: true }, label: _('Cluster'), disabled: !new_host %>
|
|
19
|
-
<% if computers.count > 1
|
|
19
|
+
<% if computers.count > 1 -%>
|
|
20
20
|
<%= select_f f, :computer_name, computers, :name, :name, {}, label: _('Computer Name'), disabled: !new_host, onload: 'hypervHostChange(this);', onchange: 'hypervHostChange(this);' %>
|
|
21
21
|
<% end -%>
|
|
22
|
-
<% end %>
|
|
23
|
-
<div class="clearfix">
|
|
24
|
-
<div class="form-group">
|
|
25
|
-
<label class="col-md-2 control-label">Available resources</label>
|
|
26
|
-
<div class="col-md-4 help-block" id="hypervComputerInformation">
|
|
27
|
-
<% computers.each do |host| -%>
|
|
28
|
-
<table class="hyperv-host-info" style="<%= (host.name == f.object.computer_name) ? '' : 'display: none' %>" data-host="<%= host.name %>">
|
|
29
|
-
<tbody>
|
|
30
|
-
<tr>
|
|
31
|
-
<td>CPU:</td>
|
|
32
|
-
<td style="padding-left:0.5em;"><%= host.logical_processor_count %></td>
|
|
33
|
-
</tr>
|
|
34
|
-
<tr>
|
|
35
|
-
<td>Memory:</td>
|
|
36
|
-
<td style="padding-left:0.5em;"><%= number_to_human_size(host.memory_capacity) %></td>
|
|
37
|
-
</tr>
|
|
38
|
-
</tbody>
|
|
39
|
-
</table>
|
|
40
22
|
<% end -%>
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
23
|
<% cluster_errors.each do |err| -%>
|
|
46
24
|
<div class="alert alert-warning alert-dismissable">
|
|
47
25
|
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
|
@@ -49,10 +27,22 @@
|
|
|
49
27
|
</div>
|
|
50
28
|
<% end -%>
|
|
51
29
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
30
|
+
<%
|
|
31
|
+
firmware_type = compute_resource.firmware_type(f.object.foreman_firmware, f.object.secure_boot_enabled)
|
|
32
|
+
-%>
|
|
33
|
+
<%= field(f, :foreman_firmware, :label => _('Firmware'), :label_help => _("Choose 'Automatic' to set the firmware based on the PXE loader of the host. If no PXE loader is selected, firmware defaults to BIOS."), :label_size => "col-md-2") do
|
|
34
|
+
compute_resource.firmware_types.collect do |type, name|
|
|
35
|
+
enabled = new_vm
|
|
36
|
+
enabled ||= firmware_type != :bios && type.to_s.start_with?('uefi')
|
|
37
|
+
|
|
38
|
+
radio_button_f f, :foreman_firmware, { :checked => (firmware_type == type), :disabled => !enabled, :value => type, :text => _(name) }
|
|
39
|
+
end.join(' ').html_safe
|
|
40
|
+
end %>
|
|
41
|
+
<%= checkbox_f f, :tpm_enabled, { help_inline: _('Add Virtual TPM module to the VM.'),
|
|
42
|
+
label: _('Virtual TPM'),
|
|
43
|
+
label_help: _('Only compatible with UEFI firmware.'),
|
|
44
|
+
label_size: 'col-md-2' } %>
|
|
45
|
+
<%= select_f f, :boot_device, hyperv_boot_devices, :first, :last, {}, label: _('Boot device'), label_help: _('Has effect only for network based provisioning'), class: 'col-md-2' if new_vm %>
|
|
56
46
|
|
|
57
47
|
<%= counter_f f, :processor_count, label: _('CPUs'), label_size: 'col-md-2' %>
|
|
58
48
|
<%= byte_size_f f, :memory_startup, label: _('Memory (Startup)'), label_size: 'col-md-2' %>
|
|
@@ -61,7 +51,7 @@
|
|
|
61
51
|
<%= byte_size_f f, :memory_maximum, class: 'col-md-2', label: _('Memory Maximum'), disabled: !f.object.dynamic_memory_enabled %>
|
|
62
52
|
<%= byte_size_f f, :memory_minimum, class: 'col-md-2', label: _('Memory Minimum'), disabled: !f.object.dynamic_memory_enabled %>
|
|
63
53
|
|
|
64
|
-
<% checked = params[:host] && params[:host][:compute_attributes] && params[:host][:compute_attributes][:start] || '1'
|
|
54
|
+
<% checked = params[:host] && params[:host][:compute_attributes] && params[:host][:compute_attributes][:start] || '1' -%>
|
|
65
55
|
<%= checkbox_f f, :start, { checked: (checked == '1'), help_inline: _("Power ON this machine"), label: _('Start'), label_size: "col-md-2"} if new_host && controller_name != "compute_attributes" %>
|
|
66
56
|
|
|
67
57
|
<%= textarea_f f, :notes, rows: '3', label: _('Notes') %>
|
|
@@ -9,26 +9,26 @@
|
|
|
9
9
|
|
|
10
10
|
<%# If Access mode %>
|
|
11
11
|
<div data-hyperv-vlan-mode="access" class="<%= 'hide' unless f.object.vlan_operation_mode.to_s == 'Access' %>">
|
|
12
|
-
<%= number_f f, :access_vlan_id, label: _('Access VLAN'), label_size: 'col-md-3', size: 'col-md-8', required: true, disabled: (f.object.vlan_operation_mode.to_s != 'Access') %>
|
|
12
|
+
<%= number_f f, :access_vlan_id, label: _('Access VLAN'), label_size: 'col-md-3', size: 'col-md-8', required: true, disabled: (f.object.vlan_operation_mode.to_s != 'Access') %>
|
|
13
13
|
</div>
|
|
14
14
|
<%# If Trunk mode %>
|
|
15
15
|
<div data-hyperv-vlan-mode="trunk" class="<%= 'hide' unless f.object.vlan_operation_mode.to_s == 'Trunk' %>">
|
|
16
|
-
<%= number_f f, :native_vlan_id, label: _('Native VLAN'), label_size: 'col-md-3', size: 'col-md-8', required: true, disabled: (f.object.vlan_operation_mode.to_s != 'Trunk') %>
|
|
17
|
-
<%= text_f f, :allowed_vlan_ids, placeholder: '10,20-40,50', label: _('Allowed VLANs'), label_size: 'col-md-3', size: 'col-md-8', required: true, disabled: (f.object.vlan_operation_mode.to_s != 'Trunk') %>
|
|
16
|
+
<%= number_f f, :native_vlan_id, label: _('Native VLAN'), label_size: 'col-md-3', size: 'col-md-8', required: true, disabled: (f.object.vlan_operation_mode.to_s != 'Trunk') %>
|
|
17
|
+
<%= text_f f, :allowed_vlan_ids, placeholder: '10,20-40,50', label: _('Allowed VLANs'), label_size: 'col-md-3', size: 'col-md-8', required: true, disabled: (f.object.vlan_operation_mode.to_s != 'Trunk') %>
|
|
18
18
|
</div>
|
|
19
19
|
<%# If Private mode %>
|
|
20
20
|
<div data-hyperv-vlan-mode="private" class="<%= 'hide' unless f.object.vlan_operation_mode.to_s == 'Private' %>">
|
|
21
|
-
<%= select_f f, :vlan_private_mode, hyperv_private_vlan_modes, :first, :last, {},
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<%= number_f f, :primary_vlan_id, label: _('Primary VLAN'), label_size: 'col-md-3', size: 'col-md-8', required: true, disabled: (f.object.vlan_operation_mode.to_s != 'Private') %>
|
|
26
|
-
<%# If Isolated or Community private mode %>
|
|
27
|
-
<div data-hyperv-vlan-private-mode="singular" class="<%= 'hide' if f.object.vlan_private_mode.to_s == 'Promiscuous' %>">
|
|
28
|
-
<%= number_f f, :secondary_vlan_id, label: _('Secondary VLAN'), label_size: 'col-md-3', size: 'col-md-8', required: true, disabled: (f.object.vlan_operation_mode.to_s != 'Private' || f.object.vlan_private_mode.to_s == 'Promiscuous') %>
|
|
29
|
-
</div>
|
|
30
|
-
<%# If Promiscuous private mode %>
|
|
31
|
-
<div data-hyperv-vlan-private-mode="plural" class="<%= 'hide' unless f.object.vlan_private_mode.to_s == 'Promiscuous' %>">
|
|
32
|
-
<%= text_f f, :secondary_vlan_ids, placeholder: '10,20-40,50', label: _('Secondary VLANs'), label_size: 'col-md-3', size: 'col-md-8', required: true, disabled: (f.object.vlan_operation_mode.to_s != 'Private' || f.object.vlan_private_mode.to_s != 'Promiscuous') %>
|
|
33
|
-
</div>
|
|
21
|
+
<%= select_f f, :vlan_private_mode, hyperv_private_vlan_modes, :first, :last, {},
|
|
22
|
+
label: _('VLAN private mode'), label_size: 'col-md-3', size: 'col-md-8',
|
|
23
|
+
onchange: 'hypervVLANPrivateModeChange(this);',
|
|
24
|
+
disabled: (f.object.vlan_operation_mode.to_s != 'Private') %>
|
|
25
|
+
<%= number_f f, :primary_vlan_id, label: _('Primary VLAN'), label_size: 'col-md-3', size: 'col-md-8', required: true, disabled: (f.object.vlan_operation_mode.to_s != 'Private') %>
|
|
26
|
+
<%# If Isolated or Community private mode %>
|
|
27
|
+
<div data-hyperv-vlan-private-mode="singular" class="<%= 'hide' if f.object.vlan_private_mode.to_s == 'Promiscuous' %>">
|
|
28
|
+
<%= number_f f, :secondary_vlan_id, label: _('Secondary VLAN'), label_size: 'col-md-3', size: 'col-md-8', required: true, disabled: (f.object.vlan_operation_mode.to_s != 'Private' || f.object.vlan_private_mode.to_s == 'Promiscuous') %>
|
|
29
|
+
</div>
|
|
30
|
+
<%# If Promiscuous private mode %>
|
|
31
|
+
<div data-hyperv-vlan-private-mode="plural" class="<%= 'hide' unless f.object.vlan_private_mode.to_s == 'Promiscuous' %>">
|
|
32
|
+
<%= text_f f, :secondary_vlan_ids, placeholder: '10,20-40,50', label: _('Secondary VLANs'), label_size: 'col-md-3', size: 'col-md-8', required: true, disabled: (f.object.vlan_operation_mode.to_s != 'Private' || f.object.vlan_private_mode.to_s != 'Promiscuous') %>
|
|
33
|
+
</div>
|
|
34
34
|
</div>
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
<%= f.hidden_field :id %>
|
|
5
5
|
<%= f.hidden_field :basename %>
|
|
6
6
|
<% end -%>
|
|
7
|
-
<%= text_f f, :basename, label: _('Name'),
|
|
7
|
+
<%= text_f f, :basename, label: _('Name'), label_help: _('This is the VHD filename on disk, without extension'), required: true, disabled: f.object.persisted? %>
|
|
8
8
|
<%= byte_size_f f, :size_bytes, label: _('Size') %>
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: foreman_hyperv
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alexander Olofsson
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '0.
|
|
18
|
+
version: '0.2'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '0.
|
|
25
|
+
version: '0.2'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: bundler
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -51,6 +51,34 @@ dependencies:
|
|
|
51
51
|
- - ">="
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
53
|
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rubocop
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: rubocop-rails
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
54
82
|
- !ruby/object:Gem::Dependency
|
|
55
83
|
name: minitest
|
|
56
84
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -105,7 +133,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
105
133
|
requirements:
|
|
106
134
|
- - ">="
|
|
107
135
|
- !ruby/object:Gem::Version
|
|
108
|
-
version: '0'
|
|
136
|
+
version: '3.0'
|
|
109
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
138
|
requirements:
|
|
111
139
|
- - ">="
|