virtualbox 0.5.4 → 0.6.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.
Files changed (162) hide show
  1. data/.gitignore +2 -1
  2. data/Gemfile +1 -1
  3. data/Rakefile +1 -1
  4. data/Readme.md +5 -21
  5. data/VERSION +1 -1
  6. data/docs/WhatsNew.md +9 -47
  7. data/lib/virtualbox.rb +7 -30
  8. data/lib/virtualbox/abstract_model.rb +25 -5
  9. data/lib/virtualbox/abstract_model/attributable.rb +5 -1
  10. data/lib/virtualbox/abstract_model/dirty.rb +2 -0
  11. data/lib/virtualbox/abstract_model/interface_attributes.rb +96 -0
  12. data/lib/virtualbox/abstract_model/relatable.rb +19 -8
  13. data/lib/virtualbox/appliance.rb +59 -0
  14. data/lib/virtualbox/audio_adapter.rb +44 -0
  15. data/lib/virtualbox/bios.rb +44 -0
  16. data/lib/virtualbox/com.rb +23 -0
  17. data/lib/virtualbox/com/abstract_enum.rb +42 -0
  18. data/lib/virtualbox/com/abstract_implementer.rb +43 -0
  19. data/lib/virtualbox/com/abstract_interface.rb +165 -0
  20. data/lib/virtualbox/com/ffi/interface.rb +141 -0
  21. data/lib/virtualbox/com/ffi/interfaces.rb +42 -0
  22. data/lib/virtualbox/com/ffi/util.rb +101 -0
  23. data/lib/virtualbox/com/ffi/vboxxpcomc.rb +31 -0
  24. data/lib/virtualbox/com/ffi_interface.rb +65 -0
  25. data/lib/virtualbox/com/implementer/base.rb +52 -0
  26. data/lib/virtualbox/com/implementer/ffi.rb +350 -0
  27. data/lib/virtualbox/com/implementer/mscom.rb +165 -0
  28. data/lib/virtualbox/com/implementer/nil.rb +10 -0
  29. data/lib/virtualbox/com/interface/appliance.rb +20 -0
  30. data/lib/virtualbox/com/interface/audio_adapter.rb +13 -0
  31. data/lib/virtualbox/com/interface/audio_controller_type.rb +9 -0
  32. data/lib/virtualbox/com/interface/audio_driver_type.rb +9 -0
  33. data/lib/virtualbox/com/interface/bios_boot_menu_mode.rb +9 -0
  34. data/lib/virtualbox/com/interface/bios_settings.rb +19 -0
  35. data/lib/virtualbox/com/interface/clipboard_mode.rb +9 -0
  36. data/lib/virtualbox/com/interface/console.rb +48 -0
  37. data/lib/virtualbox/com/interface/cpu_property_type.rb +9 -0
  38. data/lib/virtualbox/com/interface/device_type.rb +9 -0
  39. data/lib/virtualbox/com/interface/dhcp_server.rb +20 -0
  40. data/lib/virtualbox/com/interface/firmware_type.rb +9 -0
  41. data/lib/virtualbox/com/interface/guest_os_type.rb +21 -0
  42. data/lib/virtualbox/com/interface/host.rb +40 -0
  43. data/lib/virtualbox/com/interface/host_network_interface.rb +28 -0
  44. data/lib/virtualbox/com/interface/host_network_interface_medium_type.rb +9 -0
  45. data/lib/virtualbox/com/interface/host_network_interface_status.rb +9 -0
  46. data/lib/virtualbox/com/interface/host_network_interface_type.rb +9 -0
  47. data/lib/virtualbox/com/interface/host_usb_device.rb +11 -0
  48. data/lib/virtualbox/com/interface/host_usb_device_filter.rb +11 -0
  49. data/lib/virtualbox/com/interface/hw_virt_ex_property_type.rb +9 -0
  50. data/lib/virtualbox/com/interface/machine.rb +103 -0
  51. data/lib/virtualbox/com/interface/machine_state.rb +12 -0
  52. data/lib/virtualbox/com/interface/medium.rb +48 -0
  53. data/lib/virtualbox/com/interface/medium_attachment.rb +16 -0
  54. data/lib/virtualbox/com/interface/medium_format.rb +16 -0
  55. data/lib/virtualbox/com/interface/medium_state.rb +9 -0
  56. data/lib/virtualbox/com/interface/medium_type.rb +9 -0
  57. data/lib/virtualbox/com/interface/medium_variant.rb +9 -0
  58. data/lib/virtualbox/com/interface/network_adapter.rb +28 -0
  59. data/lib/virtualbox/com/interface/network_adapter_type.rb +9 -0
  60. data/lib/virtualbox/com/interface/network_attachment_type.rb +9 -0
  61. data/lib/virtualbox/com/interface/nsiexception.rb +21 -0
  62. data/lib/virtualbox/com/interface/nsisupports.rb +13 -0
  63. data/lib/virtualbox/com/interface/parallel_port.rb +15 -0
  64. data/lib/virtualbox/com/interface/port_mode.rb +9 -0
  65. data/lib/virtualbox/com/interface/progress.rb +58 -0
  66. data/lib/virtualbox/com/interface/serial_port.rb +17 -0
  67. data/lib/virtualbox/com/interface/session.rb +16 -0
  68. data/lib/virtualbox/com/interface/session_state.rb +9 -0
  69. data/lib/virtualbox/com/interface/session_type.rb +9 -0
  70. data/lib/virtualbox/com/interface/shared_folder.rb +15 -0
  71. data/lib/virtualbox/com/interface/snapshot.rb +18 -0
  72. data/lib/virtualbox/com/interface/storage_bus.rb +9 -0
  73. data/lib/virtualbox/com/interface/storage_controller.rb +21 -0
  74. data/lib/virtualbox/com/interface/storage_controller_type.rb +9 -0
  75. data/lib/virtualbox/com/interface/system_properties.rb +35 -0
  76. data/lib/virtualbox/com/interface/usb_controller.rb +18 -0
  77. data/lib/virtualbox/com/interface/usb_device.rb +22 -0
  78. data/lib/virtualbox/com/interface/usb_device_filter.rb +21 -0
  79. data/lib/virtualbox/com/interface/usb_device_filter_action.rb +9 -0
  80. data/lib/virtualbox/com/interface/usb_device_state.rb +9 -0
  81. data/lib/virtualbox/com/interface/virtual_box_error_info.rb +15 -0
  82. data/lib/virtualbox/com/interface/virtual_system_description.rb +17 -0
  83. data/lib/virtualbox/com/interface/virtual_system_description_type.rb +12 -0
  84. data/lib/virtualbox/com/interface/virtual_system_description_value_type.rb +9 -0
  85. data/lib/virtualbox/com/interface/virtualbox.rb +54 -0
  86. data/lib/virtualbox/com/interface/vrdp_auth_type.rb +9 -0
  87. data/lib/virtualbox/com/interface/vrdp_server.rb +17 -0
  88. data/lib/virtualbox/com/mscom_interface.rb +22 -0
  89. data/lib/virtualbox/com/util.rb +18 -0
  90. data/lib/virtualbox/dvd.rb +7 -94
  91. data/lib/virtualbox/exceptions.rb +24 -0
  92. data/lib/virtualbox/ext/glob_loader.rb +22 -0
  93. data/lib/virtualbox/ext/logger.rb +38 -0
  94. data/lib/virtualbox/ext/platform.rb +1 -1
  95. data/lib/virtualbox/extra_data.rb +25 -37
  96. data/lib/virtualbox/forwarded_port.rb +35 -13
  97. data/lib/virtualbox/global.rb +22 -80
  98. data/lib/virtualbox/hard_drive.rb +30 -97
  99. data/lib/virtualbox/lib.rb +82 -0
  100. data/lib/virtualbox/media.rb +7 -6
  101. data/lib/virtualbox/medium.rb +138 -0
  102. data/lib/virtualbox/medium_attachment.rb +61 -0
  103. data/lib/virtualbox/network_adapter.rb +134 -0
  104. data/lib/virtualbox/shared_folder.rb +53 -78
  105. data/lib/virtualbox/storage_controller.rb +76 -20
  106. data/lib/virtualbox/system_properties.rb +74 -0
  107. data/lib/virtualbox/usb_controller.rb +55 -0
  108. data/lib/virtualbox/version.rb +15 -0
  109. data/lib/virtualbox/virtual_system_description.rb +47 -0
  110. data/lib/virtualbox/vm.rb +160 -272
  111. data/test/test_helper.rb +0 -108
  112. data/test/virtualbox/abstract_model/attributable_test.rb +7 -1
  113. data/test/virtualbox/abstract_model/dirty_test.rb +1 -1
  114. data/test/virtualbox/abstract_model/interface_attributes_test.rb +169 -0
  115. data/test/virtualbox/abstract_model/relatable_test.rb +20 -0
  116. data/test/virtualbox/abstract_model_test.rb +40 -5
  117. data/test/virtualbox/appliance_test.rb +152 -0
  118. data/test/virtualbox/audio_adapter_test.rb +83 -0
  119. data/test/virtualbox/bios_test.rb +83 -0
  120. data/test/virtualbox/com/abstract_enum_test.rb +48 -0
  121. data/test/virtualbox/com/abstract_implementer_test.rb +39 -0
  122. data/test/virtualbox/com/abstract_interface_test.rb +139 -0
  123. data/test/virtualbox/com/ffi/interface_test.rb +249 -0
  124. data/test/virtualbox/com/ffi/util_test.rb +86 -0
  125. data/test/virtualbox/com/ffi_interface_test.rb +42 -0
  126. data/test/virtualbox/com/implementer/base_test.rb +37 -0
  127. data/test/virtualbox/com/implementer/ffi_test.rb +519 -0
  128. data/test/virtualbox/com/implementer/mscom_test.rb +208 -0
  129. data/test/virtualbox/com/mscom_interface_test.rb +17 -0
  130. data/test/virtualbox/com/util_test.rb +17 -0
  131. data/test/virtualbox/dvd_test.rb +4 -95
  132. data/test/virtualbox/ext/platform_test.rb +8 -0
  133. data/test/virtualbox/extra_data_test.rb +78 -102
  134. data/test/virtualbox/forwarded_port_test.rb +57 -7
  135. data/test/virtualbox/global_test.rb +25 -115
  136. data/test/virtualbox/hard_drive_test.rb +49 -212
  137. data/test/virtualbox/lib_test.rb +93 -0
  138. data/test/virtualbox/medium_attachment_test.rb +147 -0
  139. data/test/virtualbox/medium_test.rb +192 -0
  140. data/test/virtualbox/network_adapter_test.rb +160 -0
  141. data/test/virtualbox/shared_folder_test.rb +144 -160
  142. data/test/virtualbox/storage_controller_test.rb +166 -45
  143. data/test/virtualbox/system_properties_test.rb +87 -0
  144. data/test/virtualbox/usb_controller_test.rb +104 -0
  145. data/test/virtualbox/version_test.rb +34 -0
  146. data/test/virtualbox/virtual_system_description_test.rb +61 -0
  147. data/test/virtualbox/vm_test.rb +288 -322
  148. data/test/virtualbox_test.rb +1 -9
  149. data/virtualbox.gemspec +139 -23
  150. metadata +143 -27
  151. data/lib/virtualbox/attached_device.rb +0 -249
  152. data/lib/virtualbox/command.rb +0 -109
  153. data/lib/virtualbox/image.rb +0 -137
  154. data/lib/virtualbox/nic.rb +0 -111
  155. data/lib/virtualbox/system_property.rb +0 -55
  156. data/lib/virtualbox/usb.rb +0 -72
  157. data/test/virtualbox/attached_device_test.rb +0 -303
  158. data/test/virtualbox/command_test.rb +0 -152
  159. data/test/virtualbox/image_test.rb +0 -190
  160. data/test/virtualbox/nic_test.rb +0 -76
  161. data/test/virtualbox/system_property_test.rb +0 -71
  162. data/test/virtualbox/usb_test.rb +0 -35
@@ -0,0 +1,61 @@
1
+ module VirtualBox
2
+ # Represents the attachment of a medium (DVD, Hard Drive, etc) to a
3
+ # virtual machine, and specifically to a {StorageController}.
4
+ class MediumAttachment < AbstractModel
5
+ attribute :parent, :readonly => true, :property => false
6
+ attribute :controller_name, :readonly => :true, :property => :controller
7
+ attribute :port, :readonly => true
8
+ attribute :device, :readonly => true
9
+ attribute :passthrough, :readonly => true
10
+ attribute :type, :readonly => true
11
+ relationship :medium, :Medium
12
+ relationship :storage_controller, :StorageController
13
+
14
+ class <<self
15
+ # Populates a relationship with another model.
16
+ #
17
+ # **This method typically won't be used except internally.**
18
+ #
19
+ # @return [Array<MediumAttachment>]
20
+ def populate_relationship(caller, imachine)
21
+ relation = Proxies::Collection.new(caller)
22
+
23
+ imachine.medium_attachments.each do |ima|
24
+ relation << new(caller, ima)
25
+ end
26
+
27
+ relation
28
+ end
29
+ end
30
+
31
+ def initialize(parent, imedium_attachment)
32
+ populate_attributes({:parent => parent}, :ignore_relationships => true)
33
+ initialize_attributes(imedium_attachment)
34
+ end
35
+
36
+ def initialize_attributes(ima)
37
+ load_interface_attributes(ima)
38
+ populate_relationship(:medium, ima.medium)
39
+ populate_relationship(:storage_controller, self)
40
+ end
41
+
42
+ # Detaches the medium from it's parent virtual machine. Note that this
43
+ # **does not delete** the `medium` which this attachment references; it
44
+ # merely removes the assocation of said medium with this attachment's
45
+ # virtual machine.
46
+ def detach
47
+ parent.with_open_session do |session|
48
+ machine = session.machine
49
+
50
+ machine.detach_device(storage_controller.name, port, device)
51
+ end
52
+ end
53
+
54
+ # Destroy this medium attachment. This simply detaches the medium attachment.
55
+ # This will also delete the medium if that option is specified.
56
+ def destroy(opts={})
57
+ detach
58
+ medium.destroy(opts[:destroy_medium] == :delete) if opts[:destroy_medium] && medium
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,134 @@
1
+ module VirtualBox
2
+ # Represents a single NIC (Network Interface Card) of a virtual machine.
3
+ #
4
+ # **Currently, new NICs can't be created, so the only way to get this
5
+ # object is through a {VM}'s `nics` relationship.**
6
+ #
7
+ # # Editing a NIC
8
+ #
9
+ # Nics can be modified directly in their relationship to other
10
+ # virtual machines. When {VM#save} is called, it will also save any
11
+ # changes to its relationships.
12
+ #
13
+ # vm = VirtualBox::VM.find("foo")
14
+ # vm.nics[0].macaddress = @new_mac_address
15
+ # vm.save
16
+ #
17
+ # # Attributes
18
+ #
19
+ # Properties of the model are exposed using standard ruby instance
20
+ # methods which are generated on the fly. Because of this, they are not listed
21
+ # below as available instance methods.
22
+ #
23
+ # These attributes can be accessed and modified via standard ruby-style
24
+ # `instance.attribute` and `instance.attribute=` methods. The attributes are
25
+ # listed below. If you aren't sure what this means or you can't understand
26
+ # why the below is listed, please read {Attributable}.
27
+ #
28
+ # attribute :parent, :readonly => :readonly
29
+ # attribute :nic
30
+ # attribute :nictype
31
+ # attribute :macaddress
32
+ # attribute :cableconnected
33
+ # attribute :bridgeadapter
34
+ #
35
+ class NetworkAdapter < AbstractModel
36
+ attribute :parent, :readonly => true, :property => false
37
+ attribute :slot, :readonly => true
38
+ attribute :enabled
39
+ attribute :attachment_type
40
+ attribute :adapter_type
41
+ attribute :mac_address
42
+ attribute :cable_connected
43
+ attribute :nat_network
44
+ attribute :internal_network
45
+ attribute :host_interface
46
+ attribute :interface, :readonly => true, :property => false
47
+
48
+ class <<self
49
+ # Populates the nic relationship for anything which is related to it.
50
+ #
51
+ # **This method typically won't be used except internally.**
52
+ #
53
+ # @return [Array<Nic>]
54
+ def populate_relationship(caller, imachine)
55
+ relation = Proxies::Collection.new(caller)
56
+
57
+ # Get the count of network adapters
58
+ count = imachine.parent.system_properties.network_adapter_count
59
+
60
+ count.times do |i|
61
+ relation << new(caller, imachine.get_network_adapter(i))
62
+ end
63
+
64
+ relation
65
+ end
66
+
67
+ # Saves the relationship. This simply calls {#save} on every
68
+ # member of the relationship.
69
+ #
70
+ # **This method typically won't be used except internally.**
71
+ def save_relationship(caller, items)
72
+ items.each do |item|
73
+ item.save
74
+ end
75
+ end
76
+ end
77
+
78
+ def initialize(caller, inetwork)
79
+ super()
80
+
81
+ initialize_attributes(caller, inetwork)
82
+ end
83
+
84
+ # Initializes the attributes of an existing shared folder.
85
+ def initialize_attributes(parent, inetwork)
86
+ # Set the parent and interface
87
+ write_attribute(:parent, parent)
88
+ write_attribute(:interface, inetwork)
89
+
90
+ # Load the interface attributes
91
+ load_interface_attributes(inetwork)
92
+
93
+ # Clear dirtiness, since this should only be called initially and
94
+ # therefore shouldn't affect dirtiness
95
+ clear_dirty!
96
+
97
+ # But this is an existing record
98
+ existing_record!
99
+ end
100
+
101
+ # Save a network adapter.
102
+ def save
103
+ modify_adapter do |adapter|
104
+ save_attachment_type(adapter)
105
+ save_changed_interface_attributes(adapter)
106
+ end
107
+ end
108
+
109
+ # Saves the attachment type. This should never be called directly. Instead,
110
+ # {save} should be called, which will call this method if appropriate.
111
+ def save_attachment_type(adapter)
112
+ return unless attachment_type_changed?
113
+
114
+ mapping = {
115
+ :nat => :attach_to_nat,
116
+ :bridged => :attach_to_bridged_interface,
117
+ :internal => :attach_to_internal_network,
118
+ :host_only => :attach_to_host_only_interface
119
+ }
120
+
121
+ adapter.send(mapping[attachment_type])
122
+ clear_dirty!(:attachment_type)
123
+ end
124
+
125
+ # Opens a session, yields the adapter and then saves the machine at
126
+ # the end
127
+ def modify_adapter
128
+ parent.with_open_session do |session|
129
+ machine = session.machine
130
+ yield machine.get_network_adapter(slot)
131
+ end
132
+ end
133
+ end
134
+ end
@@ -85,9 +85,11 @@ module VirtualBox
85
85
  # attribute :hostpath
86
86
  #
87
87
  class SharedFolder < AbstractModel
88
- attribute :parent, :readonly => :readonly
88
+ attribute :parent, :readonly => true, :property => false
89
89
  attribute :name
90
- attribute :hostpath
90
+ attribute :host_path
91
+ attribute :writable, :default => true
92
+ attribute :accessible, :readonly => true
91
93
 
92
94
  class <<self
93
95
  # Populates the shared folder relationship for anything which is related to it.
@@ -95,13 +97,11 @@ module VirtualBox
95
97
  # **This method typically won't be used except internally.**
96
98
  #
97
99
  # @return [Array<SharedFolder>]
98
- def populate_relationship(caller, doc)
100
+ def populate_relationship(caller, imachine)
99
101
  relation = Proxies::Collection.new(caller)
100
102
 
101
- counter = 1
102
- doc.css("Hardware SharedFolders SharedFolder").each do |folder|
103
- relation << new(counter, caller, folder)
104
- counter += 1
103
+ imachine.shared_folders.each do |ishared|
104
+ relation << new(caller, ishared)
105
105
  end
106
106
 
107
107
  relation
@@ -111,10 +111,9 @@ module VirtualBox
111
111
  # member of the relationship.
112
112
  #
113
113
  # **This method typically won't be used except internally.**
114
- def save_relationship(caller, data)
115
- # Just call save on each folder with the VM
116
- data.each do |sf|
117
- sf.save
114
+ def save_relationship(caller, items)
115
+ items.each do |item|
116
+ item.save
118
117
  end
119
118
  end
120
119
  end
@@ -127,51 +126,31 @@ module VirtualBox
127
126
  # @overload initialize(index, caller, data)
128
127
  # Creates an SharedFolder for a relationship. **This should
129
128
  # never be called except internally.**
130
- # @param [Integer] index Index of the shared folder
131
129
  # @param [Object] caller The parent
132
130
  # @param [Hash] data A hash of data which must be used
133
131
  # to extract the relationship data.
134
132
  def initialize(*args)
135
133
  super()
136
134
 
137
- if args.length == 3
138
- initialize_for_relationship(*args)
139
- elsif args.length == 1
140
- initialize_for_data(*args)
141
- elsif args.length == 0
142
- return
143
- else
144
- raise NoMethodError.new
135
+ if args.length == 2
136
+ initialize_attributes(*args)
145
137
  end
146
138
  end
147
139
 
148
- # Initializes the record for use in a relationship. This
149
- # is automatically called by {#initialize} if it has three
150
- # parameters.
151
- #
152
- # **This method typically won't be used except internally.**
153
- def initialize_for_relationship(index, caller, data)
154
- # Setup the index specific attributes
155
- populate_data = {}
156
- data.attributes.each do |key, value|
157
- populate_data[key.downcase.to_sym] = value.to_s
158
- end
140
+ # Initializes the attributes of an existing shared folder.
141
+ def initialize_attributes(parent, ishared)
142
+ # Set the parent
143
+ write_attribute(:parent, parent)
159
144
 
160
- populate_attributes(populate_data.merge({
161
- :parent => caller
162
- }))
163
- end
145
+ # Load the interface attributes
146
+ load_interface_attributes(ishared)
164
147
 
165
- # Initializes a record with initial data but keeping it a "new
166
- # record." This is called automatically if {#initialize} is given
167
- # only a single parameter. View {#initialize} for documentation.
168
- def initialize_for_data(data)
169
- self.class.attributes.each do |name, options|
170
- data[options[:populate_key]] = data[name]
171
- end
148
+ # Clear dirtiness, since this should only be called initially and
149
+ # therefore shouldn't affect dirtiness
150
+ clear_dirty!
172
151
 
173
- populate_attributes(data)
174
- new_record!
152
+ # But this is an existing record
153
+ existing_record!
175
154
  end
176
155
 
177
156
  # Validates a shared folder.
@@ -180,33 +159,35 @@ module VirtualBox
180
159
 
181
160
  validates_presence_of :parent
182
161
  validates_presence_of :name
183
- validates_presence_of :hostpath
162
+ validates_presence_of :host_path
184
163
  end
185
164
 
186
165
  # Saves or creates a shared folder.
187
- #
188
- # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
189
- # will be raised if the command failed.
190
- # @return [Boolean] True if command was successful, false otherwise.
191
- def save(raise_errors=false)
192
- return true unless changed?
193
-
194
- if !valid?
195
- raise Exceptions::ValidationFailedException.new(errors) if raise_errors
196
- return false
166
+ def save
167
+ return true if !new_record? && !changed?
168
+ raise Exceptions::ValidationFailedException.new(errors) if !valid?
169
+
170
+ if !new_record?
171
+ # If its not a new record, any changes will require a new shared
172
+ # folder to be created, so we first destroy it then recreate it.
173
+ destroy
197
174
  end
198
175
 
199
- # If this isn't a new record, we destroy it first
200
- destroy(raise_errors) if !new_record?
176
+ create
177
+ end
178
+
179
+ # Creates a new shared folder. This method should not be called directly.
180
+ # Instead, {save} should always be called, which will do the right thing.
181
+ def create
182
+ return unless new_record?
183
+
184
+ parent.with_open_session do |session|
185
+ machine = session.machine
186
+ machine.create_shared_folder(name, host_path, writable)
187
+ end
201
188
 
202
- Command.vboxmanage("sharedfolder", "add", parent.name, "--name", name, "--hostpath", hostpath)
203
189
  existing_record!
204
190
  clear_dirty!
205
-
206
- true
207
- rescue Exceptions::CommandFailedException
208
- raise if raise_errors
209
- false
210
191
  end
211
192
 
212
193
  # Relationship callback when added to a collection. This is automatically
@@ -219,20 +200,14 @@ module VirtualBox
219
200
  # from the host system. Instead, it simply removes the mapping to the
220
201
  # virtual machine, meaning it will no longer be possible to mount it
221
202
  # from within the virtual machine.
222
- #
223
- # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
224
- # will be raised if the command failed.
225
- # @return [Boolean] True if command was successful, false otherwise.
226
- def destroy(raise_errors=false)
227
- # If the name changed, we have to be sure to use the previous
228
- # one.
229
- name_value = name_changed? ? name_was : name
230
-
231
- Command.vboxmanage("sharedfolder", "remove", parent.name, "--name", name_value)
232
- true
233
- rescue Exceptions::CommandFailedException
234
- raise if raise_errors
235
- false
236
- end
203
+ def destroy
204
+ parent.with_open_session do |session|
205
+ machine = session.machine
206
+ machine.remove_shared_folder(name)
207
+ end
208
+
209
+ # Mark as a new record so if it is saved again, it will create it
210
+ new_record!
211
+ end
237
212
  end
238
213
  end
@@ -40,11 +40,12 @@ module VirtualBox
40
40
  # relationship :devices, AttachedDevice, :dependent => :destroy
41
41
  #
42
42
  class StorageController < AbstractModel
43
- attribute :parent, :readonly => true
44
- attribute :name
45
- attribute :type
46
- attribute :ports, :populate_key => :portcount
47
- relationship :devices, AttachedDevice, :dependent => :destroy
43
+ attribute :parent, :readonly => true, :property => false
44
+ attribute :interface, :readonly => true, :property => false
45
+ attribute :name, :readonly => true
46
+ attribute :port_count
47
+ attribute :bus, :readonly => true
48
+ attribute :controller_type
48
49
 
49
50
  class <<self
50
51
  # Populates a relationship with another model.
@@ -52,18 +53,41 @@ module VirtualBox
52
53
  # **This method typically won't be used except internally.**
53
54
  #
54
55
  # @return [Array<StorageController>]
55
- def populate_relationship(caller, doc)
56
+ def populate_relationship(caller, data)
57
+ if data.is_a?(COM::Interface::Machine)
58
+ populate_array_relationship(caller, data)
59
+ elsif data.is_a?(MediumAttachment)
60
+ populate_attachment_relationship(caller, data)
61
+ end
62
+ end
63
+
64
+ # Populates a has many relationship for a {VM}.
65
+ #
66
+ # **This method typically won't be used except internally.**
67
+ #
68
+ # @return [Array<StorageController>]
69
+ def populate_array_relationship(caller, imachine)
56
70
  relation = Proxies::Collection.new(caller)
57
71
 
58
- counter = 0
59
- doc.css("StorageControllers StorageController").each do |sc|
60
- relation << new(counter, caller, sc)
61
- counter += 1
72
+ imachine.storage_controllers.each do |icontroller|
73
+ relation << new(caller, icontroller)
62
74
  end
63
75
 
64
76
  relation
65
77
  end
66
78
 
79
+ # Populates a single relationship for a {MediumAttachment}.
80
+ #
81
+ # **This method typically won't be used except internally.**
82
+ #
83
+ # @return [Array<StorageController>]
84
+ def populate_attachment_relationship(caller, attachment)
85
+ # Find the storage controller with the matching name
86
+ attachment.parent.storage_controllers.find do |sc|
87
+ sc.name == attachment.controller_name
88
+ end
89
+ end
90
+
67
91
  # Destroys a relationship with another model.
68
92
  #
69
93
  # **This method typically won't be used except internally.**
@@ -75,8 +99,8 @@ module VirtualBox
75
99
  # member of the relationship.
76
100
  #
77
101
  # **This method typically won't be used except internally.**
78
- def save_relationship(caller, data)
79
- data.each do |sc|
102
+ def save_relationship(caller, controllers)
103
+ controllers.each do |sc|
80
104
  sc.save
81
105
  end
82
106
  end
@@ -86,19 +110,51 @@ module VirtualBox
86
110
  # this method shouldn't be called. Instead, storage controllers
87
111
  # can be retrieved through relationships of other models such
88
112
  # as {VM}.
89
- def initialize(index, caller, data)
113
+ def initialize(caller, icontroller)
90
114
  super()
91
115
 
92
- @index = index
116
+ populate_attributes({
117
+ :parent => caller,
118
+ :interface => icontroller
119
+ }, :ignore_relationships => true)
120
+ load_interface_attributes(icontroller)
121
+ clear_dirty!
122
+ end
93
123
 
94
- # Setup the index specific attributes
95
- populate_data = {}
96
- data.attributes.each do |key,value|
97
- populate_data[key.downcase.to_sym] = value.to_s
124
+ # Retrieves the array of medium attachments related to this storage controller.
125
+ # This is not implemented as a relationship simply because it would have been
126
+ # difficult to do so (circular) and its not really necessary.
127
+ def medium_attachments
128
+ parent.medium_attachments.find_all do |ma|
129
+ ma.storage_controller == self
98
130
  end
131
+ end
99
132
 
100
- populate_attributes(populate_data.merge({:parent => caller}), :ignore_relationships => true)
101
- populate_relationship(:devices, data)
133
+ # Saves the storage controller. This method shouldn't be called directly.
134
+ # Instead, {VM#save} should be called, which will save all attached storage
135
+ # controllers as well. This will setup the proper parameter for `interface`
136
+ # here.
137
+ def save
138
+ parent.with_open_session do |session|
139
+ machine = session.machine
140
+ save_changed_interface_attributes(machine.get_storage_controller_by_name(name))
141
+ end
142
+ end
143
+
144
+ # Destroys the storage controller. This first detaches all attachments on this
145
+ # storage controller. Note that this does *not* delete the media on the attachments,
146
+ # unless specified by the options.
147
+ def destroy(*args)
148
+ # First remove all attachments
149
+ medium_attachments.each do |ma|
150
+ ma.destroy(*args)
151
+ end
152
+
153
+ # Finally, remove ourselves
154
+ parent.with_open_session do |session|
155
+ machine = session.machine
156
+ machine.remove_storage_controller(name)
157
+ end
102
158
  end
103
159
  end
104
160
  end