fog-hyperv 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +11 -0
- data/Gemfile +4 -0
- data/README.md +53 -0
- data/Rakefile +10 -0
- data/fog-hyperv.gemspec +28 -0
- data/lib/fog/bin/hyperv.rb +28 -0
- data/lib/fog/collection.rb +114 -0
- data/lib/fog/hyperv.rb +123 -0
- data/lib/fog/hyperv/compute.rb +327 -0
- data/lib/fog/hyperv/fog_extensions/enum.rb +51 -0
- data/lib/fog/hyperv/models/compute/bios.rb +52 -0
- data/lib/fog/hyperv/models/compute/cluster.rb +37 -0
- data/lib/fog/hyperv/models/compute/clusters.rb +11 -0
- data/lib/fog/hyperv/models/compute/com_port.rb +22 -0
- data/lib/fog/hyperv/models/compute/dvd_drive.rb +62 -0
- data/lib/fog/hyperv/models/compute/dvd_drives.rb +11 -0
- data/lib/fog/hyperv/models/compute/firmware.rb +52 -0
- data/lib/fog/hyperv/models/compute/floppy_drive.rb +48 -0
- data/lib/fog/hyperv/models/compute/floppy_drives.rb +11 -0
- data/lib/fog/hyperv/models/compute/hard_drive.rb +110 -0
- data/lib/fog/hyperv/models/compute/hard_drives.rb +11 -0
- data/lib/fog/hyperv/models/compute/host.rb +20 -0
- data/lib/fog/hyperv/models/compute/hosts.rb +15 -0
- data/lib/fog/hyperv/models/compute/network_adapter.rb +142 -0
- data/lib/fog/hyperv/models/compute/network_adapters.rb +19 -0
- data/lib/fog/hyperv/models/compute/server.rb +192 -0
- data/lib/fog/hyperv/models/compute/servers.rb +30 -0
- data/lib/fog/hyperv/models/compute/switch.rb +58 -0
- data/lib/fog/hyperv/models/compute/switches.rb +15 -0
- data/lib/fog/hyperv/models/compute/vhd.rb +100 -0
- data/lib/fog/hyperv/models/compute/vhds.rb +16 -0
- data/lib/fog/hyperv/requests/compute/add_vm_hard_disk_drive.rb +12 -0
- data/lib/fog/hyperv/requests/compute/add_vm_network_adapter.rb +12 -0
- data/lib/fog/hyperv/requests/compute/connect_vm_network_adapter.rb +12 -0
- data/lib/fog/hyperv/requests/compute/disconnect_vm_network_adapter.rb +12 -0
- data/lib/fog/hyperv/requests/compute/get_cluster.rb +11 -0
- data/lib/fog/hyperv/requests/compute/get_cluster_node.rb +19 -0
- data/lib/fog/hyperv/requests/compute/get_vhd.rb +34 -0
- data/lib/fog/hyperv/requests/compute/get_vm.rb +20 -0
- data/lib/fog/hyperv/requests/compute/get_vm_bios.rb +21 -0
- data/lib/fog/hyperv/requests/compute/get_vm_dvd_drive.rb +20 -0
- data/lib/fog/hyperv/requests/compute/get_vm_firmware.rb +21 -0
- data/lib/fog/hyperv/requests/compute/get_vm_floppy_disk_drive.rb +20 -0
- data/lib/fog/hyperv/requests/compute/get_vm_group.rb +23 -0
- data/lib/fog/hyperv/requests/compute/get_vm_hard_disk_drive.rb +20 -0
- data/lib/fog/hyperv/requests/compute/get_vm_host.rb +12 -0
- data/lib/fog/hyperv/requests/compute/get_vm_host_cluster.rb +25 -0
- data/lib/fog/hyperv/requests/compute/get_vm_network_adapter.rb +27 -0
- data/lib/fog/hyperv/requests/compute/get_vm_switch.rb +27 -0
- data/lib/fog/hyperv/requests/compute/mock_files/get_cluster.json +1 -0
- data/lib/fog/hyperv/requests/compute/mock_files/get_cluster_node.json +1 -0
- data/lib/fog/hyperv/requests/compute/mock_files/get_vhd.json +1 -0
- data/lib/fog/hyperv/requests/compute/mock_files/get_vm.json +1 -0
- data/lib/fog/hyperv/requests/compute/mock_files/get_vm_bios.json +1 -0
- data/lib/fog/hyperv/requests/compute/mock_files/get_vm_dvd_drive.json +1 -0
- data/lib/fog/hyperv/requests/compute/mock_files/get_vm_firmware.json +1 -0
- data/lib/fog/hyperv/requests/compute/mock_files/get_vm_floppy_disk_drive.json +1 -0
- data/lib/fog/hyperv/requests/compute/mock_files/get_vm_hard_disk_drive.json +1 -0
- data/lib/fog/hyperv/requests/compute/mock_files/get_vm_host.json +1 -0
- data/lib/fog/hyperv/requests/compute/mock_files/get_vm_network_adapter.json +1 -0
- data/lib/fog/hyperv/requests/compute/mock_files/get_vm_switch.json +1 -0
- data/lib/fog/hyperv/requests/compute/new_vhd.rb +12 -0
- data/lib/fog/hyperv/requests/compute/new_vm.rb +15 -0
- data/lib/fog/hyperv/requests/compute/new_vm_switch.rb +13 -0
- data/lib/fog/hyperv/requests/compute/remove_item.rb +13 -0
- data/lib/fog/hyperv/requests/compute/remove_vm.rb +15 -0
- data/lib/fog/hyperv/requests/compute/remove_vm_hard_disk_drive.rb +12 -0
- data/lib/fog/hyperv/requests/compute/remove_vm_network_adapter.rb +12 -0
- data/lib/fog/hyperv/requests/compute/restart_vm.rb +15 -0
- data/lib/fog/hyperv/requests/compute/set_vm.rb +12 -0
- data/lib/fog/hyperv/requests/compute/set_vm_bios.rb +13 -0
- data/lib/fog/hyperv/requests/compute/set_vm_dvd_drive.rb +12 -0
- data/lib/fog/hyperv/requests/compute/set_vm_firmware.rb +13 -0
- data/lib/fog/hyperv/requests/compute/set_vm_hard_disk_drive.rb +12 -0
- data/lib/fog/hyperv/requests/compute/set_vm_network_adapter.rb +12 -0
- data/lib/fog/hyperv/requests/compute/set_vm_switch.rb +13 -0
- data/lib/fog/hyperv/requests/compute/start_vm.rb +15 -0
- data/lib/fog/hyperv/requests/compute/stop_vm.rb +15 -0
- data/lib/fog/hyperv/version.rb +5 -0
- data/lib/fog/model.rb +64 -0
- data/test/fog/hyperv_test.rb +7 -0
- data/test/test_helper.rb +4 -0
- metadata +199 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
module Fog
|
2
|
+
module Attributes
|
3
|
+
class Enum < Default
|
4
|
+
attr_reader :values
|
5
|
+
|
6
|
+
def initialize(model, name, options)
|
7
|
+
@values = options.fetch(:values, [])
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_setter
|
12
|
+
model.class_eval <<-EOS, __FILE__, __LINE__
|
13
|
+
def #{name}=(new_#{name})
|
14
|
+
if new_#{name}.is_a?(Fixnum)
|
15
|
+
raise Fog::Hyperv::Errors::ServiceError, "\#{new_#{name}} is not in the range (0..#{values.length - 1})" unless new_#{name} >= 0 && new_#{name} < #{values.length}
|
16
|
+
attributes[:#{name}] = #{values}[new_#{name}]
|
17
|
+
elsif new_#{name}.nil?
|
18
|
+
attributes[:#{name}] = nil
|
19
|
+
else
|
20
|
+
new_#{name} = new_#{name}.to_s.to_sym unless new_#{name}.is_a? String
|
21
|
+
raise Fog::Hyperv::Errors::ServiceError, "\#{new_#{name}} is not one of #{values.is_a?(Hash) ? values.values : values})" unless #{(values.is_a?(Hash) ? values.values : values)}.include? new_#{name}
|
22
|
+
attributes[:#{name}] = new_#{name}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
EOS
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_getter
|
29
|
+
model.class_eval <<-EOS, __FILE__, __LINE__
|
30
|
+
def #{name}_num
|
31
|
+
return nil if self.#{name}.nil?
|
32
|
+
if self.#{name}.is_a?(Fixnum)
|
33
|
+
self.#{name}
|
34
|
+
else
|
35
|
+
if #{values}.is_a?(Hash)
|
36
|
+
#{values}.key(self.#{name})
|
37
|
+
else
|
38
|
+
#{values}.index(self.#{name})
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def #{name}_values
|
44
|
+
#{values}.freeze
|
45
|
+
end
|
46
|
+
EOS
|
47
|
+
super
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Fog
|
2
|
+
module Compute
|
3
|
+
class Hyperv
|
4
|
+
class Bios < Fog::Hyperv::Model
|
5
|
+
identity :vm_id, type: :string
|
6
|
+
|
7
|
+
attribute :computer_name, type: :string
|
8
|
+
# attribute :is_deleted, type: :boolean
|
9
|
+
attribute :num_lock_enabled, type: :boolean
|
10
|
+
# TODO? Enum values; :CD, :IDE, :LegacyNetworkAdapter, :Floppy (, :VHD, :NetworkAdapter)
|
11
|
+
attribute :startup_order, type: :array
|
12
|
+
attribute :vm_name, type: :string
|
13
|
+
|
14
|
+
def save
|
15
|
+
requires :computer_name, :vm_name
|
16
|
+
|
17
|
+
raise Fog::Hyperv::Errors::ServiceError, "Can't create Bios instances" unless persisted?
|
18
|
+
|
19
|
+
data = service.set_vm_bios(
|
20
|
+
computer_name: computer_name,
|
21
|
+
vm_name: vm_name,
|
22
|
+
passthru: true,
|
23
|
+
|
24
|
+
disable_num_lock: changed?(:num_lock_enabled) && !num_lock_enabled,
|
25
|
+
enable_num_lock: changed?(:num_lock_enabled) && num_lock_enabled,
|
26
|
+
startup_order: changed!(:startup_order),
|
27
|
+
|
28
|
+
_return_fields: self.class.attributes,
|
29
|
+
_json_depth: 1
|
30
|
+
)
|
31
|
+
|
32
|
+
merge_attributes(data)
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def reload
|
37
|
+
requires :computer_name, :vm_name
|
38
|
+
|
39
|
+
data = service.get_vm_bios(
|
40
|
+
computer_name: computer_name,
|
41
|
+
vm_name: vm_name,
|
42
|
+
|
43
|
+
_return_fields: self.class.attributes,
|
44
|
+
_json_depth: 1
|
45
|
+
)
|
46
|
+
merge_attributes(data.attributes)
|
47
|
+
self
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Fog
|
2
|
+
module Compute
|
3
|
+
class Hyperv
|
4
|
+
class Cluster < Fog::Hyperv::Model
|
5
|
+
identity :id, type: :string
|
6
|
+
|
7
|
+
attribute :description, type: :string
|
8
|
+
attribute :domain, type: :string
|
9
|
+
attribute :name, type: :string
|
10
|
+
|
11
|
+
def nodes
|
12
|
+
[service.get_cluster_node(cluster: name, _return_fields: [:description, :name, :node_name])].flatten
|
13
|
+
end
|
14
|
+
|
15
|
+
def servers
|
16
|
+
@servers ||= service.servers.class.new \
|
17
|
+
cluster: self,
|
18
|
+
service: service
|
19
|
+
end
|
20
|
+
|
21
|
+
def reload
|
22
|
+
requires_one :domain, :name
|
23
|
+
|
24
|
+
data = service.get_cluster(
|
25
|
+
domain: domain,
|
26
|
+
name: name,
|
27
|
+
|
28
|
+
_return_fields: self.class.attributes,
|
29
|
+
_json_depth: 1
|
30
|
+
)
|
31
|
+
merge_attributes(data.attributes)
|
32
|
+
self
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Fog
|
2
|
+
module Compute
|
3
|
+
class Hyperv
|
4
|
+
class ComPort < Fog::Hyperv::Model
|
5
|
+
identity :id
|
6
|
+
|
7
|
+
attribute :computer_name
|
8
|
+
attribute :debugger_mode, type: :enum, values: [ :On, :Off ]
|
9
|
+
attribute :name
|
10
|
+
attribute :path
|
11
|
+
|
12
|
+
def save
|
13
|
+
raise Fog::Errors::NotImplemented
|
14
|
+
end
|
15
|
+
|
16
|
+
def reload
|
17
|
+
raise Fog::Errors::NotImplemented
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Fog
|
2
|
+
module Compute
|
3
|
+
class Hyperv
|
4
|
+
class DvdDrive < Fog::Hyperv::Model
|
5
|
+
identity :id
|
6
|
+
|
7
|
+
attribute :computer_name
|
8
|
+
# attribute :is_deleted
|
9
|
+
attribute :name
|
10
|
+
attribute :path
|
11
|
+
attribute :pool_name
|
12
|
+
attribute :controller_location
|
13
|
+
attribute :controller_number
|
14
|
+
attribute :controller_type, type: :enum, values: [ :IDE, :SCSI ]
|
15
|
+
attribute :dvd_media_type, type: :enum, values: [ :None, :ISO, :Passthrough ]
|
16
|
+
attribute :vm_id
|
17
|
+
attribute :vm_name
|
18
|
+
# TODO? VM Snapshots?
|
19
|
+
#
|
20
|
+
attr_accessor :to_controller_number, :to_controller_location
|
21
|
+
|
22
|
+
def save
|
23
|
+
requires :computer_name, :vm_name
|
24
|
+
|
25
|
+
data = service.set_vm_dvd_drive(
|
26
|
+
computer_name: computer_name,
|
27
|
+
vm_name: vm_name,
|
28
|
+
passthru: true,
|
29
|
+
|
30
|
+
controller_number: controller_number,
|
31
|
+
controller_location: controller_location,
|
32
|
+
resource_pool_name: pool_name,
|
33
|
+
path: path || '$null',
|
34
|
+
to_controller_number: to_controller_number,
|
35
|
+
to_controller_location: to_controller_location,
|
36
|
+
|
37
|
+
_return_fields: self.class.attributes,
|
38
|
+
_json_depth: 1
|
39
|
+
)
|
40
|
+
merge_attributes(data)
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def reload
|
45
|
+
requires :computer_name, :vm_name
|
46
|
+
|
47
|
+
data = collection.get(
|
48
|
+
computer_name: computer_name,
|
49
|
+
vm_name: vm_name,
|
50
|
+
controller_location: controller_location,
|
51
|
+
controller_number: controller_number,
|
52
|
+
|
53
|
+
_return_fields: self.class.attributes,
|
54
|
+
_json_depth: 1
|
55
|
+
)
|
56
|
+
merge_attributes(data.attributes)
|
57
|
+
self
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Fog
|
2
|
+
module Compute
|
3
|
+
class Hyperv
|
4
|
+
class Firmware < Fog::Hyperv::Model
|
5
|
+
identity :vm_id
|
6
|
+
|
7
|
+
attribute :boot_order
|
8
|
+
attribute :computer_name
|
9
|
+
attribute :console_mode, type: :enum, values: [ :Default, :COM1, :COM2, :None ]
|
10
|
+
# attribute :is_deleted
|
11
|
+
attribute :preferred_network_boot_protocol, type: :enum, values: [ :IPv4, :IPv6 ]
|
12
|
+
attribute :secure_boot, type: :enum, values: [ :On, :Off ]
|
13
|
+
attribute :vm_name
|
14
|
+
|
15
|
+
def save
|
16
|
+
requires :computetr_name, :vm_name
|
17
|
+
|
18
|
+
raise Fog::Hyperv::Errors::ServiceError, "Can't create Firmware instances" unless persisted?
|
19
|
+
|
20
|
+
data = service.set_firmware(
|
21
|
+
computer_name: computer_name,
|
22
|
+
vm_name: vm_name,
|
23
|
+
passthru: true,
|
24
|
+
|
25
|
+
enable_secure_boot: changed?(:secure_boot) ? (secure_boot && 'On' || 'Off') : nil,
|
26
|
+
preferred_network_boot_protocol: changed!(:preferred_network_boot_protocol),
|
27
|
+
console_mode: changed!(:console_mode),
|
28
|
+
|
29
|
+
_return_fields: self.class.attributes
|
30
|
+
)
|
31
|
+
|
32
|
+
merge_attributes(data)
|
33
|
+
@old = dup
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def reload
|
38
|
+
requires :computer_name, :vm_name
|
39
|
+
|
40
|
+
data = service.get_firmware(
|
41
|
+
computer_name: computer_name,
|
42
|
+
vm_name: vm_name,
|
43
|
+
|
44
|
+
_return_fields: self.class.attribute
|
45
|
+
)
|
46
|
+
merge_attributes(data.attributes)
|
47
|
+
self
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Fog
|
2
|
+
module Compute
|
3
|
+
class Hyperv
|
4
|
+
class FloppyDrive < Fog::Hyperv::Model
|
5
|
+
identity :id
|
6
|
+
|
7
|
+
attribute :computer_name
|
8
|
+
attribute :disk
|
9
|
+
attribute :is_deleted
|
10
|
+
attribute :name
|
11
|
+
attribute :path
|
12
|
+
attribute :pool_name
|
13
|
+
attribute :vm_id
|
14
|
+
attribute :vm_name
|
15
|
+
# TODO? VM Snapshots?
|
16
|
+
#
|
17
|
+
|
18
|
+
def save
|
19
|
+
requires :computer_name, :vm_name
|
20
|
+
|
21
|
+
data = service.set_vm_floppy_disk_drive(
|
22
|
+
computer_name: computer_name,
|
23
|
+
vm_name: vm_name,
|
24
|
+
passthru: true,
|
25
|
+
|
26
|
+
resource_pool_name: pool_name,
|
27
|
+
path: path,
|
28
|
+
|
29
|
+
_return_fields: self.class.attributes,
|
30
|
+
_json_depth: 1
|
31
|
+
)
|
32
|
+
|
33
|
+
merge_attributes(data)
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def reload
|
38
|
+
data = collection.get(
|
39
|
+
computer_name: computer_name,
|
40
|
+
vm_name: vm_name
|
41
|
+
)
|
42
|
+
merge_attributes(data.attributes)
|
43
|
+
self
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Fog
|
2
|
+
module Compute
|
3
|
+
class Hyperv
|
4
|
+
class HardDrive < Fog::Hyperv::Model
|
5
|
+
identity :id
|
6
|
+
|
7
|
+
attribute :computer_name
|
8
|
+
attribute :controller_location
|
9
|
+
attribute :controller_number
|
10
|
+
attribute :controller_type, type: :enum, values: [ :IDE, :SCSI ]
|
11
|
+
attribute :disk
|
12
|
+
# attribute :is_deleted
|
13
|
+
attribute :maximum_iops
|
14
|
+
attribute :minimum_iops
|
15
|
+
attribute :name
|
16
|
+
attribute :path
|
17
|
+
attribute :pool_name
|
18
|
+
attribute :support_persistent_reservations
|
19
|
+
attribute :vm_id
|
20
|
+
attribute :vm_name
|
21
|
+
# TODO? VM Snapshots?
|
22
|
+
|
23
|
+
def vhd
|
24
|
+
return nil unless path && computer_name
|
25
|
+
@vhd ||= Fog::Compute::Hyperv::Vhd.new(service.get_vhd(computer_name: computer_name, path: path).merge(service: service))
|
26
|
+
end
|
27
|
+
|
28
|
+
def size_bytes
|
29
|
+
vhd && vhd.size_bytes || 0
|
30
|
+
end
|
31
|
+
|
32
|
+
def size_bytes=(bytes)
|
33
|
+
vhd.size_bytes = bytes if vhd
|
34
|
+
end
|
35
|
+
|
36
|
+
def save
|
37
|
+
requires :computer_name, :vm_name
|
38
|
+
|
39
|
+
if persisted?
|
40
|
+
data = service.set_vm_hard_disk_drive(
|
41
|
+
computer_name: old.computer_name,
|
42
|
+
vm_name: old.vm_name,
|
43
|
+
controller_location: old.controller_location,
|
44
|
+
controller_number: old.controller_number,
|
45
|
+
controller_type: old.controller_type,
|
46
|
+
|
47
|
+
disk_number: changed?(:disk) && disk && disk.number,
|
48
|
+
maximum_iops: changed?(:maximum_iops) && maximum_iops,
|
49
|
+
minimum_iops: changed?(:minimum_iops) && minimum_iops,
|
50
|
+
path: changed?(:path) && path,
|
51
|
+
resource_pool_name: changed?(:pool_name) && pool_name,
|
52
|
+
support_persistent_reservations: changed?(:support_persistent_reservations) && support_persistent_reservations,
|
53
|
+
to_controller_location: changed?(:controller_location) && controller_location,
|
54
|
+
to_controller_number: changed?(:controller_number) && controller_number,
|
55
|
+
to_controller_type: changed?(:controller_type) && controller_type,
|
56
|
+
|
57
|
+
passthru: true,
|
58
|
+
_return_fields: self.class.attributes,
|
59
|
+
_json_depth: 1
|
60
|
+
)
|
61
|
+
@vhd = nil if changed?(:path)
|
62
|
+
else
|
63
|
+
possible = %i(computer_name controller_location controller_number controller_type path vm_name).freeze
|
64
|
+
data = service.add_vm_hard_disk_drive(
|
65
|
+
attributes.select { |k, _v| possible.include? k }.merge(
|
66
|
+
disk_number: disk && disk.number,
|
67
|
+
resource_pool_name: pool_name,
|
68
|
+
|
69
|
+
passthru: true,
|
70
|
+
_return_fields: self.class.attributes,
|
71
|
+
_json_depth: 1
|
72
|
+
)
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
merge_attributes(data)
|
77
|
+
@old = dup
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
81
|
+
def reload
|
82
|
+
data = collection.get(
|
83
|
+
computer_name: computer_name,
|
84
|
+
vm_name: vm_name,
|
85
|
+
controller_location: controller_location,
|
86
|
+
controller_number: controller_number,
|
87
|
+
controller_type: controller_type
|
88
|
+
)
|
89
|
+
|
90
|
+
merge_attributes(data.attributes)
|
91
|
+
@old = data
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def destroy
|
96
|
+
return unless persisted?
|
97
|
+
|
98
|
+
service.remove_vm_hard_disk_drive(
|
99
|
+
computer_name: computer_name,
|
100
|
+
vm_name: vm_name,
|
101
|
+
|
102
|
+
controller_location: controller_location,
|
103
|
+
controller_number: controller_number,
|
104
|
+
controller_type: controller_type
|
105
|
+
)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|