fog-hyperv 0.0.9 → 0.1.1
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/README.md +12 -2
- data/lib/fog/bin/hyperv.rb +6 -4
- data/lib/fog/hyperv/collection.rb +89 -0
- data/lib/fog/hyperv/compute/models/bios.rb +70 -0
- data/lib/fog/hyperv/compute/models/cluster.rb +50 -0
- data/lib/fog/hyperv/compute/models/clusters.rb +21 -0
- data/lib/fog/hyperv/compute/models/com_port.rb +78 -0
- data/lib/fog/hyperv/compute/models/com_ports.rb +29 -0
- data/lib/fog/hyperv/compute/models/dvd_drive.rb +126 -0
- data/lib/fog/hyperv/compute/models/dvd_drives.rb +29 -0
- data/lib/fog/hyperv/compute/models/firmware.rb +78 -0
- data/lib/fog/hyperv/compute/models/floppy_drive.rb +64 -0
- data/lib/fog/hyperv/compute/models/floppy_drives.rb +18 -0
- data/lib/fog/hyperv/compute/models/hard_drive.rb +183 -0
- data/lib/fog/hyperv/compute/models/hard_drives.rb +28 -0
- data/lib/fog/hyperv/compute/models/host.rb +63 -0
- data/lib/fog/hyperv/compute/models/hosts.rb +13 -0
- data/lib/fog/hyperv/compute/models/network_adapter.rb +368 -0
- data/lib/fog/hyperv/compute/models/network_adapter_vlan.rb +172 -0
- data/lib/fog/hyperv/compute/models/network_adapters.rb +32 -0
- data/lib/fog/hyperv/compute/models/security.rb +121 -0
- data/lib/fog/hyperv/compute/models/server.rb +466 -0
- data/lib/fog/hyperv/compute/models/servers.rb +18 -0
- data/lib/fog/hyperv/compute/models/switch.rb +117 -0
- data/lib/fog/hyperv/compute/models/switches.rb +20 -0
- data/lib/fog/hyperv/compute/models/vhd.rb +210 -0
- data/lib/fog/hyperv/compute/models/vhds.rb +28 -0
- data/lib/fog/hyperv/compute/requests/add_vm_dvd_drive.rb +15 -0
- data/lib/fog/hyperv/compute/requests/add_vm_hard_disk_drive.rb +15 -0
- data/lib/fog/hyperv/compute/requests/add_vm_network_adapter.rb +24 -0
- data/lib/fog/hyperv/compute/requests/connect_vm_network_adapter.rb +41 -0
- data/lib/fog/hyperv/compute/requests/disable_vm_tpm.rb +16 -0
- data/lib/fog/hyperv/compute/requests/disconnect_vm_network_adapter.rb +29 -0
- data/lib/fog/hyperv/compute/requests/enable_vm_tpm.rb +16 -0
- data/lib/fog/hyperv/compute/requests/get_cluster.rb +11 -0
- data/lib/fog/hyperv/compute/requests/get_cluster_node.rb +22 -0
- data/lib/fog/hyperv/compute/requests/get_vhd.rb +32 -0
- data/lib/fog/hyperv/compute/requests/get_vm.rb +18 -0
- data/lib/fog/hyperv/compute/requests/get_vm_bios.rb +21 -0
- data/lib/fog/hyperv/compute/requests/get_vm_com_port.rb +17 -0
- data/lib/fog/hyperv/compute/requests/get_vm_dvd_drive.rb +25 -0
- data/lib/fog/hyperv/compute/requests/get_vm_firmware.rb +21 -0
- data/lib/fog/hyperv/compute/requests/get_vm_floppy_disk_drive.rb +16 -0
- data/lib/fog/hyperv/compute/requests/get_vm_group.rb +20 -0
- data/lib/fog/hyperv/compute/requests/get_vm_hard_disk_drive.rb +24 -0
- data/lib/fog/hyperv/compute/requests/get_vm_host.rb +9 -0
- data/lib/fog/hyperv/compute/requests/get_vm_host_cluster.rb +21 -0
- data/lib/fog/hyperv/compute/requests/get_vm_host_sbt.rb +10 -0
- data/lib/fog/hyperv/compute/requests/get_vm_key_protector.rb +16 -0
- data/lib/fog/hyperv/compute/requests/get_vm_network_adapter.rb +41 -0
- data/lib/fog/hyperv/compute/requests/get_vm_network_adapter_vlan.rb +41 -0
- data/lib/fog/hyperv/compute/requests/get_vm_security.rb +15 -0
- data/lib/fog/hyperv/compute/requests/get_vm_switch.rb +10 -0
- data/lib/fog/hyperv/compute/requests/mock_files/get_vm.json +4 -0
- data/lib/fog/hyperv/compute/requests/new_vhd.rb +9 -0
- data/lib/fog/hyperv/compute/requests/new_vm.rb +12 -0
- data/lib/fog/hyperv/compute/requests/new_vm_switch.rb +11 -0
- data/lib/fog/hyperv/compute/requests/optimize_vhd.rb +9 -0
- data/lib/fog/hyperv/compute/requests/remove_item.rb +10 -0
- data/lib/fog/hyperv/compute/requests/remove_vm.rb +16 -0
- data/lib/fog/hyperv/compute/requests/remove_vm_dvd_drive.rb +17 -0
- data/lib/fog/hyperv/compute/requests/remove_vm_hard_disk_drive.rb +17 -0
- data/lib/fog/hyperv/compute/requests/remove_vm_network_adapter.rb +29 -0
- data/lib/fog/hyperv/compute/requests/remove_vm_switch.rb +9 -0
- data/lib/fog/hyperv/compute/requests/rename_vm.rb +16 -0
- data/lib/fog/hyperv/compute/requests/rename_vm_network_adapter.rb +25 -0
- data/lib/fog/hyperv/compute/requests/rename_vm_switch.rb +16 -0
- data/lib/fog/hyperv/compute/requests/resize_vhd.rb +16 -0
- data/lib/fog/hyperv/compute/requests/restart_vm.rb +22 -0
- data/lib/fog/hyperv/compute/requests/resume_vm.rb +22 -0
- data/lib/fog/hyperv/compute/requests/save_vm.rb +22 -0
- data/lib/fog/hyperv/compute/requests/set_vm.rb +15 -0
- data/lib/fog/hyperv/compute/requests/set_vm_bios.rb +15 -0
- data/lib/fog/hyperv/compute/requests/set_vm_com_port.rb +16 -0
- data/lib/fog/hyperv/compute/requests/set_vm_dvd_drive.rb +16 -0
- data/lib/fog/hyperv/compute/requests/set_vm_firmware.rb +15 -0
- data/lib/fog/hyperv/compute/requests/set_vm_floppy_disk_drive.rb +16 -0
- data/lib/fog/hyperv/compute/requests/set_vm_hard_disk_drive.rb +16 -0
- data/lib/fog/hyperv/compute/requests/set_vm_key_protector.rb +15 -0
- data/lib/fog/hyperv/compute/requests/set_vm_network_adapter.rb +25 -0
- data/lib/fog/hyperv/compute/requests/set_vm_network_adapter_vlan.rb +25 -0
- data/lib/fog/hyperv/compute/requests/set_vm_security.rb +17 -0
- data/lib/fog/hyperv/compute/requests/set_vm_switch.rb +9 -0
- data/lib/fog/hyperv/compute/requests/start_vm.rb +22 -0
- data/lib/fog/hyperv/compute/requests/stop_vm.rb +22 -0
- data/lib/fog/hyperv/compute/requests/suspend_vm.rb +22 -0
- data/lib/fog/hyperv/compute/requests/update_vm.rb +22 -0
- data/lib/fog/hyperv/compute.rb +206 -387
- data/lib/fog/hyperv/constants.rb +24 -0
- data/lib/fog/hyperv/fog_extensions/associations/collection.rb +11 -0
- data/lib/fog/hyperv/fog_extensions/attributes/datetime.rb +28 -0
- data/lib/fog/hyperv/fog_extensions/attributes/enum.rb +139 -0
- data/lib/fog/hyperv/fog_extensions/attributes/enumarray.rb +149 -0
- data/lib/fog/hyperv/fog_extensions/attributes/timespan.rb +27 -0
- data/lib/fog/hyperv/model.rb +142 -0
- data/lib/fog/hyperv/utils/powershell.rb +88 -0
- data/lib/fog/hyperv/utils/winrm.rb +233 -0
- data/lib/fog/hyperv/version.rb +4 -1
- data/lib/fog/hyperv.rb +53 -44
- metadata +187 -105
- data/.gitignore +0 -10
- data/.travis.yml +0 -11
- data/CHANGELOG.md +0 -52
- data/Gemfile +0 -4
- data/Rakefile +0 -10
- data/fog-hyperv.gemspec +0 -25
- data/lib/fog/collection.rb +0 -152
- data/lib/fog/hyperv/fog_extensions/enum.rb +0 -85
- data/lib/fog/hyperv/models/compute/bios.rb +0 -61
- data/lib/fog/hyperv/models/compute/cluster.rb +0 -64
- data/lib/fog/hyperv/models/compute/clusters.rb +0 -15
- data/lib/fog/hyperv/models/compute/com_port.rb +0 -22
- data/lib/fog/hyperv/models/compute/dvd_drive.rb +0 -92
- data/lib/fog/hyperv/models/compute/dvd_drives.rb +0 -12
- data/lib/fog/hyperv/models/compute/firmware.rb +0 -53
- data/lib/fog/hyperv/models/compute/floppy_drive.rb +0 -53
- data/lib/fog/hyperv/models/compute/floppy_drives.rb +0 -12
- data/lib/fog/hyperv/models/compute/hard_drive.rb +0 -110
- data/lib/fog/hyperv/models/compute/hard_drives.rb +0 -11
- data/lib/fog/hyperv/models/compute/host.rb +0 -45
- data/lib/fog/hyperv/models/compute/hosts.rb +0 -15
- data/lib/fog/hyperv/models/compute/network_adapter.rb +0 -145
- data/lib/fog/hyperv/models/compute/network_adapters.rb +0 -19
- data/lib/fog/hyperv/models/compute/server.rb +0 -220
- data/lib/fog/hyperv/models/compute/servers.rb +0 -21
- data/lib/fog/hyperv/models/compute/switch.rb +0 -65
- data/lib/fog/hyperv/models/compute/switches.rb +0 -15
- data/lib/fog/hyperv/models/compute/vhd.rb +0 -101
- data/lib/fog/hyperv/models/compute/vhds.rb +0 -16
- data/lib/fog/hyperv/requests/compute/add_vm_dvd_drive.rb +0 -12
- data/lib/fog/hyperv/requests/compute/add_vm_hard_disk_drive.rb +0 -12
- data/lib/fog/hyperv/requests/compute/add_vm_network_adapter.rb +0 -12
- data/lib/fog/hyperv/requests/compute/connect_vm_network_adapter.rb +0 -12
- data/lib/fog/hyperv/requests/compute/disconnect_vm_network_adapter.rb +0 -12
- data/lib/fog/hyperv/requests/compute/get_cluster.rb +0 -11
- data/lib/fog/hyperv/requests/compute/get_cluster_node.rb +0 -19
- data/lib/fog/hyperv/requests/compute/get_vhd.rb +0 -34
- data/lib/fog/hyperv/requests/compute/get_vm.rb +0 -20
- data/lib/fog/hyperv/requests/compute/get_vm_bios.rb +0 -21
- data/lib/fog/hyperv/requests/compute/get_vm_dvd_drive.rb +0 -20
- data/lib/fog/hyperv/requests/compute/get_vm_firmware.rb +0 -19
- data/lib/fog/hyperv/requests/compute/get_vm_floppy_disk_drive.rb +0 -20
- data/lib/fog/hyperv/requests/compute/get_vm_group.rb +0 -23
- data/lib/fog/hyperv/requests/compute/get_vm_hard_disk_drive.rb +0 -20
- data/lib/fog/hyperv/requests/compute/get_vm_host.rb +0 -12
- data/lib/fog/hyperv/requests/compute/get_vm_host_cluster.rb +0 -25
- data/lib/fog/hyperv/requests/compute/get_vm_network_adapter.rb +0 -27
- data/lib/fog/hyperv/requests/compute/get_vm_switch.rb +0 -27
- data/lib/fog/hyperv/requests/compute/mock_files/get_vm.json +0 -1
- data/lib/fog/hyperv/requests/compute/new_vhd.rb +0 -12
- data/lib/fog/hyperv/requests/compute/new_vm.rb +0 -15
- data/lib/fog/hyperv/requests/compute/new_vm_switch.rb +0 -13
- data/lib/fog/hyperv/requests/compute/remove_item.rb +0 -13
- data/lib/fog/hyperv/requests/compute/remove_vm.rb +0 -15
- data/lib/fog/hyperv/requests/compute/remove_vm_dvd_drive.rb +0 -12
- data/lib/fog/hyperv/requests/compute/remove_vm_hard_disk_drive.rb +0 -12
- data/lib/fog/hyperv/requests/compute/remove_vm_network_adapter.rb +0 -12
- data/lib/fog/hyperv/requests/compute/restart_vm.rb +0 -15
- data/lib/fog/hyperv/requests/compute/set_vm.rb +0 -12
- data/lib/fog/hyperv/requests/compute/set_vm_bios.rb +0 -13
- data/lib/fog/hyperv/requests/compute/set_vm_dvd_drive.rb +0 -12
- data/lib/fog/hyperv/requests/compute/set_vm_firmware.rb +0 -13
- data/lib/fog/hyperv/requests/compute/set_vm_hard_disk_drive.rb +0 -12
- data/lib/fog/hyperv/requests/compute/set_vm_network_adapter.rb +0 -12
- data/lib/fog/hyperv/requests/compute/set_vm_network_adapter_vlan.rb +0 -12
- data/lib/fog/hyperv/requests/compute/set_vm_switch.rb +0 -13
- data/lib/fog/hyperv/requests/compute/start_vm.rb +0 -15
- data/lib/fog/hyperv/requests/compute/stop_vm.rb +0 -15
- data/lib/fog/model.rb +0 -91
- data/test/fog/hyperv_test.rb +0 -7
- data/test/test_helper.rb +0 -4
- /data/lib/fog/hyperv/{requests/compute → compute/requests}/mock_files/get_cluster.json +0 -0
- /data/lib/fog/hyperv/{requests/compute → compute/requests}/mock_files/get_cluster_node.json +0 -0
- /data/lib/fog/hyperv/{requests/compute → compute/requests}/mock_files/get_vhd.json +0 -0
- /data/lib/fog/hyperv/{requests/compute → compute/requests}/mock_files/get_vm_bios.json +0 -0
- /data/lib/fog/hyperv/{requests/compute → compute/requests}/mock_files/get_vm_dvd_drive.json +0 -0
- /data/lib/fog/hyperv/{requests/compute → compute/requests}/mock_files/get_vm_firmware.json +0 -0
- /data/lib/fog/hyperv/{requests/compute → compute/requests}/mock_files/get_vm_floppy_disk_drive.json +0 -0
- /data/lib/fog/hyperv/{requests/compute → compute/requests}/mock_files/get_vm_hard_disk_drive.json +0 -0
- /data/lib/fog/hyperv/{requests/compute → compute/requests}/mock_files/get_vm_host.json +0 -0
- /data/lib/fog/hyperv/{requests/compute → compute/requests}/mock_files/get_vm_network_adapter.json +0 -0
- /data/lib/fog/hyperv/{requests/compute → compute/requests}/mock_files/get_vm_switch.json +0 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Fog::Attributes
|
|
4
|
+
# Fog attribute type for handling DateTime values from PowerShell
|
|
5
|
+
class Hypervdatetime < Fog::Attributes::Default
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
# rubocop:disable Style/DocumentDynamicEvalDefinition
|
|
9
|
+
|
|
10
|
+
def create_setter
|
|
11
|
+
# Possible input values are;
|
|
12
|
+
# /Date(123456789)/ - time since unix epoch in milliseconds
|
|
13
|
+
# "2026-01-02T10:11:12Z" - DateTime in long-form parsable format
|
|
14
|
+
model.class_eval <<-SETTER, __FILE__, __LINE__ + 1
|
|
15
|
+
def #{name}=(new_#{name})
|
|
16
|
+
new_#{name} = new_#{name}.scan(/Date\\((\\d+)\\)/).flatten.first&.to_i if new_#{name}.include?('Date(')
|
|
17
|
+
|
|
18
|
+
if new_#{name}.respond_to?(:to_i)
|
|
19
|
+
attributes[:#{name}] = Fog::Time.at(new_#{name}.to_i / 1000.0)
|
|
20
|
+
else
|
|
21
|
+
attributes[:#{name}] = Fog::Time.parse(new_#{name}.to_s)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
SETTER
|
|
25
|
+
end
|
|
26
|
+
# rubocop:enable Style/DocumentDynamicEvalDefinition
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Fog::Attributes
|
|
4
|
+
# Fog attribute type for handling enums from PowelShell,
|
|
5
|
+
# where the value might be a number or string depending on the context
|
|
6
|
+
class Hypervenum < Default
|
|
7
|
+
attr_reader :values
|
|
8
|
+
|
|
9
|
+
def initialize(model, name, options)
|
|
10
|
+
@values = options.fetch(:values)
|
|
11
|
+
|
|
12
|
+
raise Fog::Hyperv::Errors::ServiceError, "#{values} is not a valid array or hash" \
|
|
13
|
+
unless %w[Array Hash].include?(values.class.to_s)
|
|
14
|
+
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
# rubocop:disable Style/DocumentDynamicEvalDefinition -- Reporting false positive
|
|
21
|
+
|
|
22
|
+
def ensure_value_getter
|
|
23
|
+
return if model.private_method_defined?(:"#{name}_values")
|
|
24
|
+
|
|
25
|
+
model.class_eval <<-VALUE_GETTER, __FILE__, __LINE__ + 1
|
|
26
|
+
# private
|
|
27
|
+
# def state_values
|
|
28
|
+
# { Unknown: 1, Running: 2 }.freeze
|
|
29
|
+
# end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
def #{name}_values
|
|
33
|
+
#{values}.freeze
|
|
34
|
+
end
|
|
35
|
+
VALUE_GETTER
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def create_setter
|
|
39
|
+
ensure_value_getter
|
|
40
|
+
|
|
41
|
+
# Add a setter that always stores a symbol value
|
|
42
|
+
model.class_eval <<-SETTER, __FILE__, __LINE__ + 1
|
|
43
|
+
# def state=(new_value)
|
|
44
|
+
# _values = state_values
|
|
45
|
+
# if new_value.is_a?(Numeric)
|
|
46
|
+
# # TODO: Better way to do class comparison in generated code
|
|
47
|
+
# if _values.class.to_s == 'Array'
|
|
48
|
+
# raise Fog::Hyperv::Errors::ServiceError, "\#{new_value} is not in the range (0..\#{_values.length - 1})" \
|
|
49
|
+
# unless new_value >= 0 && new_value < _values.length
|
|
50
|
+
# attributes[:state] = _values[new_value]
|
|
51
|
+
# elsif _values.class.to_s == 'Hash'
|
|
52
|
+
# raise Fog::Hyperv::Errors::ServiceError, "\#{new_value} is not one of \#{_values.values})" \
|
|
53
|
+
# unless _values.values.include? new_value
|
|
54
|
+
# attributes[:state] = _values.key(new_value)
|
|
55
|
+
# end
|
|
56
|
+
# elsif new_value.nil?
|
|
57
|
+
# attributes[:state] = nil
|
|
58
|
+
# else
|
|
59
|
+
# new_value = new_value.to_s.to_sym unless new_value.is_a? Symbol
|
|
60
|
+
# # Ensure values is the array of enum symbols
|
|
61
|
+
# _values = (_values.is_a?(Hash) ? _values.keys : _values)
|
|
62
|
+
# raise Fog::Hyperv::Errors::ServiceError, "\#{new_value.inspect} is not one of \#{_values})" \
|
|
63
|
+
# unless _values.include? new_value
|
|
64
|
+
# attributes[:state] = new_value
|
|
65
|
+
# end
|
|
66
|
+
# end
|
|
67
|
+
|
|
68
|
+
def #{name}=(new_value)
|
|
69
|
+
_values = #{name}_values
|
|
70
|
+
if new_value.is_a?(Numeric)
|
|
71
|
+
# TODO: Better way to do class comparison in generated code
|
|
72
|
+
if _values.class.to_s == 'Array'
|
|
73
|
+
raise Fog::Hyperv::Errors::ServiceError, "\#{new_value} is not in the range (0..\#{_values.length - 1})" \
|
|
74
|
+
unless new_value >= 0 && new_value < _values.length
|
|
75
|
+
attributes[:#{name}] = _values[new_value]
|
|
76
|
+
elsif _values.class.to_s == 'Hash'
|
|
77
|
+
raise Fog::Hyperv::Errors::ServiceError, "\#{new_value} is not one of \#{_values.values})" \
|
|
78
|
+
unless _values.values.include? new_value
|
|
79
|
+
attributes[:#{name}] = _values.key(new_value)
|
|
80
|
+
end
|
|
81
|
+
elsif new_value.nil?
|
|
82
|
+
attributes[:#{name}] = nil
|
|
83
|
+
else
|
|
84
|
+
new_value = new_value.to_s.to_sym unless new_value.is_a? Symbol
|
|
85
|
+
# Ensure values is the array of enum symbols
|
|
86
|
+
_values = (_values.is_a?(Hash) ? _values.keys : _values)
|
|
87
|
+
raise Fog::Hyperv::Errors::ServiceError, "\#{new_value.inspect} is not one of \#{_values})" \
|
|
88
|
+
unless _values.include? new_value
|
|
89
|
+
attributes[:#{name}] = new_value
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
SETTER
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def create_getter
|
|
96
|
+
ensure_value_getter
|
|
97
|
+
|
|
98
|
+
# Add a getter for <enum>_num to get the numeric value
|
|
99
|
+
model.class_eval <<-GETTER_NUM, __FILE__, __LINE__ + 1
|
|
100
|
+
# def state_num
|
|
101
|
+
# _values = state_values
|
|
102
|
+
# _value = attributes[:state]
|
|
103
|
+
#
|
|
104
|
+
# return nil if _value.nil?
|
|
105
|
+
# if _value.is_a?(Numeric)
|
|
106
|
+
# _value
|
|
107
|
+
# else
|
|
108
|
+
# if _values.is_a?(Hash)
|
|
109
|
+
# _values.send(:[], _value)
|
|
110
|
+
# else
|
|
111
|
+
# _values.index(_value)
|
|
112
|
+
# end
|
|
113
|
+
# end
|
|
114
|
+
# end
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def #{name}_num
|
|
118
|
+
_values = #{name}_values
|
|
119
|
+
_value = attributes[:#{name}]
|
|
120
|
+
|
|
121
|
+
return nil if _value.nil?
|
|
122
|
+
if _value.is_a?(Numeric)
|
|
123
|
+
_value
|
|
124
|
+
else
|
|
125
|
+
if _values.is_a?(Hash)
|
|
126
|
+
_values.send(:[], _value)
|
|
127
|
+
else
|
|
128
|
+
_values.index(_value)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
GETTER_NUM
|
|
133
|
+
|
|
134
|
+
# Add the default getter for the symbol value
|
|
135
|
+
super
|
|
136
|
+
end
|
|
137
|
+
# rubocop:enable Style/DocumentDynamicEvalDefinition
|
|
138
|
+
end
|
|
139
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Fog::Attributes
|
|
4
|
+
# Fog attribute type for handling arrays of enums from PowerShell,
|
|
5
|
+
# where each value might be returned as a number or string depending on the context
|
|
6
|
+
class Hypervenumarray < Default
|
|
7
|
+
attr_reader :values
|
|
8
|
+
|
|
9
|
+
def initialize(model, name, options)
|
|
10
|
+
@values = options.fetch(:values, [])
|
|
11
|
+
|
|
12
|
+
raise Fog::Hyperv::Errors::ServiceError, "#{values} is not a valid array or hash" \
|
|
13
|
+
unless %w[Array Hash].include?(values.class.to_s)
|
|
14
|
+
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
# rubocop:disable Style/DocumentDynamicEvalDefinition -- Reporting false positive
|
|
21
|
+
|
|
22
|
+
def ensure_value_getter
|
|
23
|
+
return if model.private_method_defined?(:"#{name}_values")
|
|
24
|
+
|
|
25
|
+
model.class_eval <<-VALUE_GETTER, __FILE__, __LINE__ + 1
|
|
26
|
+
# private
|
|
27
|
+
# def state_values
|
|
28
|
+
# { Unknown: 1, Running: 2 }.freeze
|
|
29
|
+
# end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
def #{name}_values
|
|
33
|
+
#{values}.freeze
|
|
34
|
+
end
|
|
35
|
+
VALUE_GETTER
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def create_setter
|
|
39
|
+
ensure_value_getter
|
|
40
|
+
|
|
41
|
+
# Add a setter that always stores a symbol value
|
|
42
|
+
model.class_eval <<-SETTER, __FILE__, __LINE__ + 1
|
|
43
|
+
# def state=(new_values)
|
|
44
|
+
# _values = state_values
|
|
45
|
+
# attributes[:state] = []
|
|
46
|
+
# new_values.each do |new_value|
|
|
47
|
+
# next unless new_value
|
|
48
|
+
# if new_value.is_a?(Numeric)
|
|
49
|
+
# # TODO: Better way to do class comparison in generated code
|
|
50
|
+
# if _values.class.to_s == 'Array'
|
|
51
|
+
# raise Fog::Hyperv::Errors::ServiceError, "\#{new_value} is not in the range (0..\#{_values.length - 1})" \
|
|
52
|
+
# unless new_value >= 0 && new_value < _values.length
|
|
53
|
+
# attributes[:state] << _values[new_value]
|
|
54
|
+
# elsif _values.class.to_s == 'Hash'
|
|
55
|
+
# raise Fog::Hyperv::Errors::ServiceError, "\#{new_value} is not one of \#{_values.values})" \
|
|
56
|
+
# unless _values.values.include? new_value
|
|
57
|
+
# attributes[:state] << _values.key(new_value)
|
|
58
|
+
# end
|
|
59
|
+
# else
|
|
60
|
+
# new_value = new_value.to_s.to_sym unless new_value.is_a? Symbol
|
|
61
|
+
# # Ensure values is the array of enum symbols
|
|
62
|
+
# _values = (_values.is_a?(Hash) ? _values.keys : _values)
|
|
63
|
+
# raise Fog::Hyperv::Errors::ServiceError, "\#{new_value.inspect} is not one of \#{_values})" \
|
|
64
|
+
# unless _values.include? new_value
|
|
65
|
+
# attributes[:state] << new_value
|
|
66
|
+
# end
|
|
67
|
+
# end
|
|
68
|
+
# end
|
|
69
|
+
|
|
70
|
+
def #{name}=(new_values)
|
|
71
|
+
_values = #{name}_values
|
|
72
|
+
new_values = [new_values].flatten unless new_values.is_a? Array
|
|
73
|
+
attributes[:#{name}] = []
|
|
74
|
+
new_values.each do |new_value|
|
|
75
|
+
next unless new_value
|
|
76
|
+
|
|
77
|
+
if new_value.is_a?(Numeric)
|
|
78
|
+
# TODO: Better way to do class comparison in generated code
|
|
79
|
+
if _values.class.to_s == 'Array'
|
|
80
|
+
raise Fog::Hyperv::Errors::ServiceError, "\#{new_value} is not in the range (0..\#{_values.length - 1})" \
|
|
81
|
+
unless new_value >= 0 && new_value < _values.length
|
|
82
|
+
attributes[:#{name}] << _values[new_value]
|
|
83
|
+
elsif _values.class.to_s == 'Hash'
|
|
84
|
+
raise Fog::Hyperv::Errors::ServiceError, "\#{new_value} is not one of \#{_values.values})" \
|
|
85
|
+
unless _values.values.include? new_value
|
|
86
|
+
attributes[:#{name}] << _values.key(new_value)
|
|
87
|
+
end
|
|
88
|
+
else
|
|
89
|
+
new_value = new_value.to_s.to_sym unless new_value.is_a? Symbol
|
|
90
|
+
# Ensure values is the array of enum symbols
|
|
91
|
+
_values = (_values.is_a?(Hash) ? _values.keys : _values)
|
|
92
|
+
raise Fog::Hyperv::Errors::ServiceError, "\#{new_value.inspect} is not one of \#{_values})" \
|
|
93
|
+
unless _values.include? new_value
|
|
94
|
+
attributes[:#{name}] << new_value
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
SETTER
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def create_getter
|
|
102
|
+
ensure_value_getter
|
|
103
|
+
|
|
104
|
+
# Add a getter for <enum>_num to get the numeric value
|
|
105
|
+
model.class_eval <<-GETTER_NUM, __FILE__, __LINE__ + 1
|
|
106
|
+
# def state_num
|
|
107
|
+
# _values = state_values
|
|
108
|
+
# _value = attributes[:state]
|
|
109
|
+
#
|
|
110
|
+
# return nil if _value.nil?
|
|
111
|
+
# _value.map do |v|
|
|
112
|
+
# if v.is_a?(Numeric)
|
|
113
|
+
# v
|
|
114
|
+
# else
|
|
115
|
+
# if _values.is_a?(Hash)
|
|
116
|
+
# _values.send(:[], v)
|
|
117
|
+
# else
|
|
118
|
+
# _values.index(v)
|
|
119
|
+
# end
|
|
120
|
+
# end
|
|
121
|
+
# end
|
|
122
|
+
# end
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def #{name}_num
|
|
126
|
+
_values = #{name}_values
|
|
127
|
+
_value = attributes[:#{name}]
|
|
128
|
+
|
|
129
|
+
return nil if _value.nil?
|
|
130
|
+
_value.map do |v|
|
|
131
|
+
if v.is_a?(Numeric)
|
|
132
|
+
v
|
|
133
|
+
else
|
|
134
|
+
if _values.is_a?(Hash)
|
|
135
|
+
_values.send(:[], v)
|
|
136
|
+
else
|
|
137
|
+
_values.index(v)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
GETTER_NUM
|
|
143
|
+
|
|
144
|
+
# Add the default getter for the symbol value
|
|
145
|
+
super
|
|
146
|
+
end
|
|
147
|
+
# rubocop:enable Style/DocumentDynamicEvalDefinition
|
|
148
|
+
end
|
|
149
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Fog::Attributes
|
|
4
|
+
# Fog attribute type for handling TimeSpan values from PowerShell
|
|
5
|
+
class Hypervtimespan < Fog::Attributes::Default
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
# rubocop:disable Style/DocumentDynamicEvalDefinition
|
|
9
|
+
|
|
10
|
+
def create_setter
|
|
11
|
+
# Possible input values are;
|
|
12
|
+
# 00:00:00 - string-converted TimeSpan
|
|
13
|
+
# {hours: 0, minutes: 0... total_seconds: 0} - hash containing the TimeSpan data
|
|
14
|
+
model.class_eval <<-SETTER, __FILE__, __LINE__ + 1
|
|
15
|
+
def #{name}=(new_#{name})
|
|
16
|
+
if new_#{name}.is_a?(Hash)
|
|
17
|
+
attributes[:#{name}] = new_#{name}[:total_seconds]
|
|
18
|
+
else
|
|
19
|
+
h, m, s = new_#{name}.split(':').map(&:to_f)
|
|
20
|
+
attributes[:#{name}] = h * 3600 + m * 60 + s
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
SETTER
|
|
24
|
+
end
|
|
25
|
+
# rubocop:enable Style/DocumentDynamicEvalDefinition
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Fog::Hyperv
|
|
4
|
+
module ModelExtends
|
|
5
|
+
# Attach a collection of sub-models
|
|
6
|
+
# @param name [Symbol] the attribute name to store the collection under
|
|
7
|
+
# @param collection_name [Symbol] the name of the collection on the service
|
|
8
|
+
# @param options [Hash] the options to create the collection attachment with
|
|
9
|
+
# @see Fog::Hyperv::Associations::Collection
|
|
10
|
+
def collection(name, collection_name = nil, options = {}) # rubocop:disable Style/OptionHash -- upstream design
|
|
11
|
+
collection_name ||= name
|
|
12
|
+
Fog::Hyperv::Associations::Collection.new(self, name, collection_name, options)
|
|
13
|
+
|
|
14
|
+
case to_s
|
|
15
|
+
when 'Fog::Hyperv::Compute::Server'
|
|
16
|
+
define_method name do
|
|
17
|
+
associations[name] ||= service.send(collection_name, vm: self, computer_name: computer_name, vm_id: id)
|
|
18
|
+
end
|
|
19
|
+
when 'Fog::Hyperv::Compute::Host'
|
|
20
|
+
define_method name do
|
|
21
|
+
associations[name] ||= service.send(collection_name, computer: self, computer_name: computer_name)
|
|
22
|
+
end
|
|
23
|
+
else
|
|
24
|
+
raise "Unknown class #{self}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
define_method :"#{name}=" do |data|
|
|
28
|
+
assoc = associations[name] || send(name)
|
|
29
|
+
assoc.clear
|
|
30
|
+
assoc.instance_variable_set :@loaded, true
|
|
31
|
+
[data].flatten.each do |obj|
|
|
32
|
+
obj = assoc.new obj if obj.is_a?(Hash)
|
|
33
|
+
assoc << obj
|
|
34
|
+
end
|
|
35
|
+
assoc
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
module ModelIncludes
|
|
41
|
+
# Has the model been modified
|
|
42
|
+
# @return [Boolean] have any attributes changed since the model was retrieved
|
|
43
|
+
def dirty?
|
|
44
|
+
dirty.any?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Get all dirty attributes
|
|
48
|
+
# @return [Array<Symbol>] all the attributes that have changed since the model was retrieved
|
|
49
|
+
def dirty
|
|
50
|
+
potential = attributes.slice(*self.class.attributes)
|
|
51
|
+
return potential unless old
|
|
52
|
+
|
|
53
|
+
potential.reject { |k, v| old.attributes[k] == v }.keys
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Get the VM this model is attached to
|
|
57
|
+
# @return [Fog::Hyperv::Compute::Server,nil] the VM this model is attached to, if any
|
|
58
|
+
def vm
|
|
59
|
+
return @vm if @vm
|
|
60
|
+
return unless respond_to?(:vm_id) && vm_id
|
|
61
|
+
|
|
62
|
+
@vm ||= service.servers.get vm_id
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Get the Computer this model is attached to
|
|
66
|
+
# @return [Fog::Hyperv::Compute::Host,nil] the Computer this model is attached to, if any
|
|
67
|
+
def computer
|
|
68
|
+
return @computer if @computer
|
|
69
|
+
return @computer ||= service.hosts.get(computer_name) if respond_to?(:computer_name) && computer_name
|
|
70
|
+
|
|
71
|
+
@computer ||= vm&.computer
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Get the Cluster this model is part of
|
|
75
|
+
# @return [Fog::Hyperv::Compute::Cluster,nil] the Cluster this model is part of, if any
|
|
76
|
+
def cluster
|
|
77
|
+
return @cluster if @cluster
|
|
78
|
+
return unless respond_to?(:cluster_name) && cluster_name
|
|
79
|
+
|
|
80
|
+
@cluster ||= service.clusters.get cluster_name
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def logger
|
|
86
|
+
service.logger
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Has any of the listed attributes been modified
|
|
90
|
+
# @param attrs [Symbol] the attributes to check for modification
|
|
91
|
+
# @param all [Boolean] check if all listed attributes have changed, instead of any
|
|
92
|
+
# @return [Boolean] are any/all of the listed attributes modified
|
|
93
|
+
def changed?(*attrs, all: false)
|
|
94
|
+
return false unless old
|
|
95
|
+
|
|
96
|
+
changed = dirty
|
|
97
|
+
if all
|
|
98
|
+
attrs.all? { |attr| changed.include? attr }
|
|
99
|
+
else
|
|
100
|
+
attrs.any? { |attr| changed.include? attr }
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Return the modified value of the given attribute - if any
|
|
105
|
+
# @return [Object,nil] the modified value of the attribute, or nil if it's unmodified
|
|
106
|
+
def changed!(attr)
|
|
107
|
+
changed?(attr) ? attributes[attr] : nil
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Return the old values of the model - i.e. what's stored in Hyper-V
|
|
111
|
+
# @return [Object,nil] the old copy of the model, or nil if there's no older version available
|
|
112
|
+
def old
|
|
113
|
+
@old ||= (persisted? ? dup.reload : nil)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# A slightly specialized Fog::Model which includes shared Hyper-V functionality
|
|
118
|
+
class Model < Fog::Model
|
|
119
|
+
extend Fog::Hyperv::ModelExtends
|
|
120
|
+
include Fog::Hyperv::ModelIncludes
|
|
121
|
+
|
|
122
|
+
def initialize(attributes = {})
|
|
123
|
+
@vm = attributes.delete :vm
|
|
124
|
+
self.attributes[:vm] = @vm if self.class.attributes.include? :vm
|
|
125
|
+
@computer = attributes.delete :computer
|
|
126
|
+
self.attributes[:computer] = @computer if self.class.attributes.include? :computer
|
|
127
|
+
@cluster = attributes.delete :cluster
|
|
128
|
+
self.attributes[:cluster] = @cluster if self.class.attributes.include? :cluster
|
|
129
|
+
|
|
130
|
+
super
|
|
131
|
+
|
|
132
|
+
@old = dup if persisted?
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def merge_attributes(attributes = {})
|
|
136
|
+
super
|
|
137
|
+
|
|
138
|
+
@old = dup
|
|
139
|
+
self
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Fog::Hyperv::Utils::Powershell
|
|
4
|
+
# Build a Powershell option map from a set of keyword arguments
|
|
5
|
+
# @param _optmap_name [String] the name of the option map to generate
|
|
6
|
+
# @param _ps_version [Integer] the major version of PowerShell to generate the option map for
|
|
7
|
+
# @param _from_json [Boolean] should the option map be built from JSON data
|
|
8
|
+
# @param options [Hash] the options to convert into a PowerShell option map
|
|
9
|
+
def self.build_optmap(_optmap_name: 'FogArgs', _ps_version: 5, _from_json: true, **_options)
|
|
10
|
+
ps_opts = Fog::Hyperv.camelize(_options)
|
|
11
|
+
if _from_json
|
|
12
|
+
if _ps_version >= 6
|
|
13
|
+
["$#{_optmap_name} = ConvertFrom-Json -AsHashtable '#{Fog::JSON.encode ps_opts}'"]
|
|
14
|
+
else
|
|
15
|
+
[
|
|
16
|
+
[
|
|
17
|
+
"$FogJsonObject = '#{Fog::JSON.encode ps_opts}'",
|
|
18
|
+
'$FogJsonParameters = ConvertFrom-Json -InputObject $FogJsonObject',
|
|
19
|
+
"$#{_optmap_name} = @{}",
|
|
20
|
+
"$FogJsonParameters.psobject.properties | Foreach { $#{_optmap_name}[$_.Name] = $_.Value }"
|
|
21
|
+
].join('; ')
|
|
22
|
+
]
|
|
23
|
+
end
|
|
24
|
+
else
|
|
25
|
+
args = ps_opts.map do |k, v|
|
|
26
|
+
"'#{k}'=#{Fog::Hyperv.shell_quote(v, always: true)}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
["$#{_optmap_name} = @{#{args.join ';'}}"]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Build a Powershell cmdlet call
|
|
34
|
+
# @param cmdlet [String] the PowerShell cmdlet to call
|
|
35
|
+
# @param args [Hash] the argument to call the cmdlet with
|
|
36
|
+
# @param _ps_version [Integer] the major version of PowerShell the call is being made for
|
|
37
|
+
#
|
|
38
|
+
# @example Running a simple cmdlet
|
|
39
|
+
# build_call 'Get-VM', { name: 'example VM' }, _ps_version: 7
|
|
40
|
+
# => "$Fogwozmqayrgsyd = ConvertFrom-Json -AsHashtable '{"Name": "example VM"}\nGet-VM @Fogwozmqayrgsyd"
|
|
41
|
+
def self.build_call(cmdlet, args = {}, _ps_version: 5)
|
|
42
|
+
return [cmdlet.gsub('@Args', '')].flatten if args.empty?
|
|
43
|
+
|
|
44
|
+
id = (cmdlet.hash ^ args.hash).abs.to_s(36)
|
|
45
|
+
optmap = "Fog#{id}"
|
|
46
|
+
|
|
47
|
+
commands = []
|
|
48
|
+
commands += build_optmap(_optmap_name: optmap, _ps_version: _ps_version, **args)
|
|
49
|
+
commands << if cmdlet.include? '@Args'
|
|
50
|
+
cmdlet.gsub('@Args', "@#{optmap}")
|
|
51
|
+
else
|
|
52
|
+
"#{cmdlet} @#{optmap}"
|
|
53
|
+
end
|
|
54
|
+
commands
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Convert Ruby data to PowerShell equivalents
|
|
58
|
+
# @param data [Object] the Ruby data to convert
|
|
59
|
+
# @param always [Boolean] should the data be included even if the equivalent would be a no-op
|
|
60
|
+
def self.shell_quote(data, always: false)
|
|
61
|
+
case data
|
|
62
|
+
when String
|
|
63
|
+
if !data.start_with?('$') && (data =~ /(^$)|\s/ || always)
|
|
64
|
+
data.gsub('`', '``')
|
|
65
|
+
.gsub(/\0/, '`0')
|
|
66
|
+
.gsub("\n", '`n')
|
|
67
|
+
.gsub("\r", '`r')
|
|
68
|
+
.inspect
|
|
69
|
+
.gsub('\"', '`"')
|
|
70
|
+
.gsub('\\\\', '\\')
|
|
71
|
+
else
|
|
72
|
+
data
|
|
73
|
+
end
|
|
74
|
+
when Hash
|
|
75
|
+
raise 'Hashes need to be run through build_optmap'
|
|
76
|
+
when Array
|
|
77
|
+
"@(#{data.map { |e| shell_quoted(e, always: true) }.join(', ')})"
|
|
78
|
+
when FalseClass
|
|
79
|
+
'$false'
|
|
80
|
+
when TrueClass
|
|
81
|
+
'$true'
|
|
82
|
+
when nil
|
|
83
|
+
'$null'
|
|
84
|
+
else
|
|
85
|
+
shell_quoted data.to_s
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|