virtualbox 0.4.3 → 0.5.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.
- data/.gitignore +3 -3
- data/Gemfile +8 -8
- data/Rakefile +2 -0
- data/Readme.md +11 -2
- data/VERSION +1 -1
- data/docs/WhatsNew.md +40 -24
- data/lib/virtualbox.rb +9 -0
- data/lib/virtualbox/abstract_model.rb +80 -10
- data/lib/virtualbox/abstract_model/attributable.rb +61 -1
- data/lib/virtualbox/abstract_model/relatable.rb +88 -6
- data/lib/virtualbox/attached_device.rb +18 -10
- data/lib/virtualbox/command.rb +13 -0
- data/lib/virtualbox/dvd.rb +35 -0
- data/lib/virtualbox/exceptions.rb +1 -0
- data/lib/virtualbox/extra_data.rb +10 -21
- data/lib/virtualbox/global.rb +126 -0
- data/lib/virtualbox/hard_drive.rb +33 -9
- data/lib/virtualbox/image.rb +2 -3
- data/lib/virtualbox/media.rb +19 -0
- data/lib/virtualbox/nic.rb +28 -67
- data/lib/virtualbox/shared_folder.rb +7 -12
- data/lib/virtualbox/storage_controller.rb +8 -36
- data/lib/virtualbox/system_property.rb +55 -0
- data/lib/virtualbox/usb.rb +72 -0
- data/lib/virtualbox/vm.rb +126 -25
- data/test/test_helper.rb +118 -12
- data/test/virtualbox/abstract_model/attributable_test.rb +55 -5
- data/test/virtualbox/abstract_model/relatable_test.rb +66 -4
- data/test/virtualbox/abstract_model_test.rb +140 -8
- data/test/virtualbox/attached_device_test.rb +10 -7
- data/test/virtualbox/command_test.rb +13 -0
- data/test/virtualbox/dvd_test.rb +50 -28
- data/test/virtualbox/extra_data_test.rb +11 -51
- data/test/virtualbox/global_test.rb +78 -0
- data/test/virtualbox/hard_drive_test.rb +34 -57
- data/test/virtualbox/image_test.rb +0 -5
- data/test/virtualbox/nic_test.rb +11 -64
- data/test/virtualbox/shared_folder_test.rb +5 -5
- data/test/virtualbox/storage_controller_test.rb +15 -30
- data/test/virtualbox/system_property_test.rb +71 -0
- data/test/virtualbox/usb_test.rb +35 -0
- data/test/virtualbox/vm_test.rb +62 -121
- data/virtualbox.gemspec +15 -2
- metadata +23 -4
@@ -72,6 +72,7 @@ module VirtualBox
|
|
72
72
|
attribute :parent, :readonly => true
|
73
73
|
attribute :uuid, :readonly => true
|
74
74
|
attribute :port
|
75
|
+
attribute :type, :readonly => true
|
75
76
|
relationship :image, Image
|
76
77
|
|
77
78
|
class <<self
|
@@ -84,10 +85,8 @@ module VirtualBox
|
|
84
85
|
relation = Proxies::Collection.new(caller)
|
85
86
|
|
86
87
|
counter = 0
|
87
|
-
|
88
|
-
|
89
|
-
nic = new(counter, caller, data)
|
90
|
-
relation.push(nic)
|
88
|
+
data.css("AttachedDevice").each do |ad|
|
89
|
+
relation << new(counter, caller, ad)
|
91
90
|
counter += 1
|
92
91
|
end
|
93
92
|
|
@@ -230,12 +229,21 @@ module VirtualBox
|
|
230
229
|
#
|
231
230
|
# **This method should never be called except internally.**
|
232
231
|
def populate_from_data(index, caller, data)
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
232
|
+
# Get the regular attributes
|
233
|
+
attrs = {}
|
234
|
+
data.attributes.each do |key, value|
|
235
|
+
attrs[key.downcase.to_sym] = value.to_s
|
236
|
+
end
|
237
|
+
|
238
|
+
# Get the Image UUID
|
239
|
+
image = data.css("Image")
|
240
|
+
if image.empty?
|
241
|
+
attrs[:uuid] = nil
|
242
|
+
else
|
243
|
+
attrs[:uuid] = image[0]["uuid"][1..-2]
|
244
|
+
end
|
245
|
+
|
246
|
+
populate_attributes(attrs.merge({ :parent => caller }))
|
239
247
|
end
|
240
248
|
end
|
241
249
|
end
|
data/lib/virtualbox/command.rb
CHANGED
@@ -14,6 +14,19 @@ module VirtualBox
|
|
14
14
|
@@vboxmanage = "VBoxManage"
|
15
15
|
|
16
16
|
class <<self
|
17
|
+
# Reads the XML file and returns a Nokogiri document. Reads the XML data
|
18
|
+
# from the specified file and returns a Nokogiri document.
|
19
|
+
#
|
20
|
+
# @param [String] File name.
|
21
|
+
# @return [Nokogiri::XML::Document]
|
22
|
+
def parse_xml(filename)
|
23
|
+
f = File.open(filename, "r")
|
24
|
+
result = Nokogiri::XML(f)
|
25
|
+
f.close
|
26
|
+
|
27
|
+
result
|
28
|
+
end
|
29
|
+
|
17
30
|
# Returns true if the last run command was a success. Obviously this
|
18
31
|
# will introduce all sorts of thread-safe problems. Those will have to
|
19
32
|
# be addressed another time.
|
data/lib/virtualbox/dvd.rb
CHANGED
@@ -22,6 +22,12 @@ module VirtualBox
|
|
22
22
|
class <<self
|
23
23
|
# Returns an array of all available DVDs as DVD objects
|
24
24
|
def all
|
25
|
+
Global.global.media.dvds
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns an array of all available DVDs by parsing the VBoxManage
|
29
|
+
# output
|
30
|
+
def all_from_command
|
25
31
|
raw = Command.vboxmanage("list", "dvds")
|
26
32
|
parse_raw(raw)
|
27
33
|
end
|
@@ -34,6 +40,26 @@ module VirtualBox
|
|
34
40
|
def empty_drive
|
35
41
|
new(:empty_drive)
|
36
42
|
end
|
43
|
+
|
44
|
+
def populate_relationship(caller, doc)
|
45
|
+
result = Proxies::Collection.new(caller)
|
46
|
+
|
47
|
+
# TODO: Location in this case is relative the vboxconfig path.
|
48
|
+
# We need to expand it. Also, size/accessible is not available.
|
49
|
+
doc.css("MediaRegistry DVDImages Image").each do |hd_node|
|
50
|
+
data = {}
|
51
|
+
hd_node.attributes.each do |key, value|
|
52
|
+
data[key.downcase.to_sym] = value.to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
# Massage UUID to proper format
|
56
|
+
data[:uuid] = data[:uuid][1..-2]
|
57
|
+
|
58
|
+
result << new(data)
|
59
|
+
end
|
60
|
+
|
61
|
+
result
|
62
|
+
end
|
37
63
|
end
|
38
64
|
|
39
65
|
def initialize(*args)
|
@@ -70,10 +96,19 @@ module VirtualBox
|
|
70
96
|
return false if empty_drive?
|
71
97
|
|
72
98
|
Command.vboxmanage("closemedium", "dvd", uuid, "--delete")
|
99
|
+
Global.reload!
|
73
100
|
true
|
74
101
|
rescue Exceptions::CommandFailedException
|
75
102
|
raise if raise_errors
|
76
103
|
false
|
77
104
|
end
|
105
|
+
|
106
|
+
# Lazy load the lazy attributes for this model.
|
107
|
+
def load_attribute(name)
|
108
|
+
# Since the lazy attributes are related, we just load them all at once
|
109
|
+
loaded_image = self.class.all_from_command.detect { |o| o.uuid == self.uuid }
|
110
|
+
|
111
|
+
write_attribute(:accessible, loaded_image.accessible)
|
112
|
+
end
|
78
113
|
end
|
79
114
|
end
|
@@ -5,6 +5,7 @@ module VirtualBox
|
|
5
5
|
class Exception < ::Exception; end
|
6
6
|
|
7
7
|
class CommandFailedException < Exception; end
|
8
|
+
class ConfigurationException < Exception; end
|
8
9
|
class InvalidRelationshipObjectException < Exception; end
|
9
10
|
class NonSettableRelationshipException < Exception; end
|
10
11
|
class ValidationFailedException < Exception; end
|
@@ -46,37 +46,26 @@ module VirtualBox
|
|
46
46
|
# @return [Array<ExtraData>]
|
47
47
|
def global(reload=false)
|
48
48
|
if !@@global_data || reload
|
49
|
-
|
50
|
-
@@global_data = parse_kv_pairs(raw)
|
49
|
+
@@global_data = Global.global.extra_data
|
51
50
|
end
|
52
51
|
|
53
52
|
@@global_data
|
54
53
|
end
|
55
54
|
|
56
|
-
# Parses the key-value pairs from the extra data enumerated
|
57
|
-
# output.
|
58
|
-
#
|
59
|
-
# @param [String] raw The raw output from enumerating extra data.
|
60
|
-
# @return [Hash]
|
61
|
-
def parse_kv_pairs(raw, parent=nil)
|
62
|
-
data = new(parent)
|
63
|
-
raw.split("\n").each do |line|
|
64
|
-
next unless line =~ /^Key: (.+?), Value: (.+?)$/i
|
65
|
-
data[$1.to_s] = $2.strip.to_s
|
66
|
-
end
|
67
|
-
|
68
|
-
data.clear_dirty!
|
69
|
-
data
|
70
|
-
end
|
71
|
-
|
72
55
|
# Populates a relationship with another model.
|
73
56
|
#
|
74
57
|
# **This method typically won't be used except internally.**
|
75
58
|
#
|
76
59
|
# @return [Array<ExtraData>]
|
77
|
-
def populate_relationship(caller,
|
78
|
-
|
79
|
-
|
60
|
+
def populate_relationship(caller, doc)
|
61
|
+
data = new(caller)
|
62
|
+
|
63
|
+
doc.css("ExtraData ExtraDataItem").each do |extradata|
|
64
|
+
data[extradata["name"].to_s] = extradata["value"].to_s
|
65
|
+
end
|
66
|
+
|
67
|
+
data.clear_dirty!
|
68
|
+
data
|
80
69
|
end
|
81
70
|
|
82
71
|
# Saves the relationship. This simply calls {#save} on every
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module VirtualBox
|
2
|
+
# Represents the VirtualBox main configuration file (VirtualBox.xml)
|
3
|
+
# which VirtualBox uses to keep track of all known virtual machines
|
4
|
+
# and images. This "global" configuration has many relationships which
|
5
|
+
# allow the user to retrieve a list of all VMs, media, global extra data,
|
6
|
+
# etc. Indeed, even methods like {VM.all} are implemented using this class.
|
7
|
+
#
|
8
|
+
# # Setting the Path to VirtualBox.xml
|
9
|
+
#
|
10
|
+
# **This is extremely important.**
|
11
|
+
#
|
12
|
+
# Much of the virtualbox gem requires a proper path to the global XML configuration
|
13
|
+
# file for VirtualBox. This path is system and installation dependent. {Global}
|
14
|
+
# does its best to guess the path by trying the default paths based on the
|
15
|
+
# platform ruby is running on, but this is hardly foolproof. If you receive an
|
16
|
+
# {Exceptions::ConfigurationException} at some point while running virtualbox,
|
17
|
+
# you should use {Global.vboxconfig=} to set the path. An example is below:
|
18
|
+
#
|
19
|
+
# # Most installations won't need to do this, since the gem "guesses"
|
20
|
+
# # the path based on OS, but if you need to set vboxconfig path
|
21
|
+
# # explicitly:
|
22
|
+
# VirtualBox::Global.vboxconfig = "~/.MyCustom/VirtualBox.xml"
|
23
|
+
#
|
24
|
+
# # Getting Global Data
|
25
|
+
#
|
26
|
+
# To retrieve the global data, use `Global.global`. This value is _cached_
|
27
|
+
# between calls, so subsequent calls will not go through the entire parsing
|
28
|
+
# process. To force a reload, set the `reload` parameter to true. Besides
|
29
|
+
# setting the parameter explicitly, some actions will implicitly force the
|
30
|
+
# global data to reload on the next call, such as saving a VM or destroying
|
31
|
+
# an image, for example.
|
32
|
+
#
|
33
|
+
# # Retrieve global data for the first time. This will parse all the
|
34
|
+
# # data.
|
35
|
+
# global_object = VirtualBox::Global.global
|
36
|
+
#
|
37
|
+
# # Subsequent calls are near-instant:
|
38
|
+
# VirtualBox::Global.global
|
39
|
+
#
|
40
|
+
# # Or we can choose to reload the data...
|
41
|
+
# reloaded_object = VirtualBox::Global.global(true)
|
42
|
+
#
|
43
|
+
# # Relationships
|
44
|
+
#
|
45
|
+
# While a global object doesn't have attributes, it does have many
|
46
|
+
# relationships. The relationships are listed below. If you don't
|
47
|
+
# understand this, read {Relatable}.
|
48
|
+
#
|
49
|
+
# relationship :vms, VM, :lazy => true
|
50
|
+
# relationship :media, Media
|
51
|
+
# relationship :extra_data, ExtraData
|
52
|
+
#
|
53
|
+
class Global < AbstractModel
|
54
|
+
# The path to the global VirtualBox XML configuration file. This is
|
55
|
+
# entirely system dependent and can be set with {vboxconfig=}. The default
|
56
|
+
# is guessed based on the platform.
|
57
|
+
#
|
58
|
+
# TODO: Windows
|
59
|
+
@@vboxconfig = if RUBY_PLATFORM.downcase.include?("darwin")
|
60
|
+
"~/Library/VirtualBox/VirtualBox.xml"
|
61
|
+
elsif RUBY_PLATFORM.downcase.include?("linux")
|
62
|
+
"~/.VirtualBox/VirtualBox.xml"
|
63
|
+
else
|
64
|
+
"Unknown"
|
65
|
+
end
|
66
|
+
|
67
|
+
relationship :vms, VM, :lazy => true
|
68
|
+
relationship :media, Media
|
69
|
+
relationship :extra_data, ExtraData
|
70
|
+
|
71
|
+
@@global_data = nil
|
72
|
+
|
73
|
+
class <<self
|
74
|
+
# Retrieves the global data. The return value of this call is cached,
|
75
|
+
# and can be reloaded by setting the `reload` parameter to true. Besides
|
76
|
+
# explicitly setting the parameter, some actions within the library
|
77
|
+
# force global to reload itself on the next call, such as saving a VM,
|
78
|
+
# or destroying an image.
|
79
|
+
#
|
80
|
+
# @param [Boolean] reload True if you want to force a reload of the data.
|
81
|
+
# @return [Global]
|
82
|
+
def global(reload = false)
|
83
|
+
if !@@global_data || reload || reload?
|
84
|
+
@@global_data = new(config)
|
85
|
+
reloaded!
|
86
|
+
end
|
87
|
+
|
88
|
+
@@global_data
|
89
|
+
end
|
90
|
+
|
91
|
+
# Sets the path to the VirtualBox.xml file. This file should already
|
92
|
+
# exist. VirtualBox itself manages this file, not this library.
|
93
|
+
#
|
94
|
+
# @param [String] Full path to the VirtualBox.xml file
|
95
|
+
def vboxconfig=(value)
|
96
|
+
@@vboxconfig = value
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the XML document of the configuration. This will raise an
|
100
|
+
# {Exceptions::ConfigurationException} if the vboxconfig file doesn't
|
101
|
+
# exist.
|
102
|
+
#
|
103
|
+
# @return [Nokogiri::XML::Document]
|
104
|
+
def config
|
105
|
+
raise Exceptions::ConfigurationException.new("The path to the global VirtualBox config must be set. See Global.vboxconfig=") unless File.exist?(File.expand_path(@@vboxconfig))
|
106
|
+
Command.parse_xml(File.expand_path(@@vboxconfig))
|
107
|
+
end
|
108
|
+
|
109
|
+
# Expands path relative to the configuration file.
|
110
|
+
#
|
111
|
+
# @return [String]
|
112
|
+
def expand_path(path)
|
113
|
+
File.expand_path(path, File.dirname(@@vboxconfig))
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def initialize(document)
|
118
|
+
@document = document
|
119
|
+
populate_attributes(@document)
|
120
|
+
end
|
121
|
+
|
122
|
+
def load_relationship(name)
|
123
|
+
populate_relationship(:vms, @document)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -78,21 +78,15 @@ module VirtualBox
|
|
78
78
|
#
|
79
79
|
class HardDrive < Image
|
80
80
|
attribute :format, :default => "VDI"
|
81
|
-
attribute :size
|
81
|
+
attribute :size, :lazy => true
|
82
82
|
|
83
83
|
class <<self
|
84
84
|
# Returns an array of all available hard drives as HardDrive
|
85
85
|
# objects.
|
86
86
|
#
|
87
|
-
# @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
|
88
|
-
# will be raised if the command failed.
|
89
87
|
# @return [Array<HardDrive>]
|
90
|
-
def all
|
91
|
-
|
92
|
-
parse_blocks(raw).collect { |v| find(v[:uuid], raise_errors) }
|
93
|
-
rescue Exceptions::CommandFailedException
|
94
|
-
raise if raise_errors
|
95
|
-
false
|
88
|
+
def all
|
89
|
+
Global.global.media.hard_drives
|
96
90
|
end
|
97
91
|
|
98
92
|
# Finds one specific hard drive by UUID or file name. If the
|
@@ -117,6 +111,27 @@ module VirtualBox
|
|
117
111
|
raise if raise_errors
|
118
112
|
nil
|
119
113
|
end
|
114
|
+
|
115
|
+
def populate_relationship(caller, doc)
|
116
|
+
result = Proxies::Collection.new(caller)
|
117
|
+
|
118
|
+
doc.css("MediaRegistry HardDisks HardDisk").each do |hd_node|
|
119
|
+
data = {}
|
120
|
+
hd_node.attributes.each do |key, value|
|
121
|
+
data[key.downcase.to_sym] = value.to_s
|
122
|
+
end
|
123
|
+
|
124
|
+
# Strip the brackets off of UUID
|
125
|
+
data[:uuid] = data[:uuid][1..-2]
|
126
|
+
|
127
|
+
# Expand location relative to config location
|
128
|
+
data[:location] = Global.expand_path(data[:location]) if data[:location]
|
129
|
+
|
130
|
+
result << new(data)
|
131
|
+
end
|
132
|
+
|
133
|
+
result
|
134
|
+
end
|
120
135
|
end
|
121
136
|
|
122
137
|
# Clone hard drive, possibly also converting formats. All formats
|
@@ -215,5 +230,14 @@ module VirtualBox
|
|
215
230
|
raise if raise_errors
|
216
231
|
false
|
217
232
|
end
|
233
|
+
|
234
|
+
# Lazy load the lazy attributes for this model.
|
235
|
+
def load_attribute(name)
|
236
|
+
# Since the lazy attributes are related, we just load them all at once
|
237
|
+
loaded_hd = self.class.find(uuid, true)
|
238
|
+
|
239
|
+
write_attribute(:size, loaded_hd.size)
|
240
|
+
write_attribute(:accessible, loaded_hd.accessible)
|
241
|
+
end
|
218
242
|
end
|
219
243
|
end
|
data/lib/virtualbox/image.rb
CHANGED
@@ -19,7 +19,7 @@ module VirtualBox
|
|
19
19
|
|
20
20
|
attribute :uuid, :readonly => true
|
21
21
|
attribute :location
|
22
|
-
attribute :accessible, :readonly => true
|
22
|
+
attribute :accessible, :readonly => true, :lazy => true
|
23
23
|
|
24
24
|
class <<self
|
25
25
|
# Parses the raw output of virtualbox into image objects. Used by
|
@@ -72,8 +72,7 @@ module VirtualBox
|
|
72
72
|
#
|
73
73
|
# @return [Array<Image>]
|
74
74
|
def populate_relationship(caller, data)
|
75
|
-
return DVD.empty_drive if data[:
|
76
|
-
return nil if data[:uuid].nil?
|
75
|
+
return DVD.empty_drive if data[:uuid].nil?
|
77
76
|
|
78
77
|
subclasses.each do |subclass|
|
79
78
|
next unless subclass.respond_to?(:all)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module VirtualBox
|
2
|
+
# Represents the media registry within the global VirtualBox configuration.
|
3
|
+
class Media < AbstractModel
|
4
|
+
attribute :parent, :readonly => true
|
5
|
+
relationship :hard_drives, HardDrive
|
6
|
+
relationship :dvds, DVD
|
7
|
+
|
8
|
+
class <<self
|
9
|
+
def populate_relationship(caller, data)
|
10
|
+
new(caller, data)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(parent, document)
|
15
|
+
populate_attributes({ :parent => parent }, :ignore_relationships => true)
|
16
|
+
populate_relationships(document)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/virtualbox/nic.rb
CHANGED
@@ -35,72 +35,22 @@ module VirtualBox
|
|
35
35
|
class Nic < AbstractModel
|
36
36
|
attribute :parent, :readonly => :readonly
|
37
37
|
attribute :nic
|
38
|
-
attribute :nictype
|
39
|
-
attribute :macaddress
|
40
|
-
attribute :cableconnected
|
38
|
+
attribute :nictype, :populate_key => "type"
|
39
|
+
attribute :macaddress, :populate_key => "MACAddress"
|
40
|
+
attribute :cableconnected, :populate_key => "cable"
|
41
41
|
attribute :bridgeadapter
|
42
42
|
|
43
43
|
class <<self
|
44
|
-
# Retrives the Nic data from human-readable vminfo. Since some data about
|
45
|
-
# nics is not exposed in the machine-readable virtual machine info, some
|
46
|
-
# extra parsing must be done to get these attributes. This method parses
|
47
|
-
# the nic-specific data from this human readable information.
|
48
|
-
#
|
49
|
-
# **This method typically won't be used except internally.**
|
50
|
-
#
|
51
|
-
# @return [Hash]
|
52
|
-
def nic_data(vmname)
|
53
|
-
raw = VM.human_info(vmname)
|
54
|
-
|
55
|
-
# Complicated chain of methods just maps parse_nic over each line,
|
56
|
-
# removing invalid ones, and then converting it into a single hash.
|
57
|
-
raw.split("\n").collect { |v| parse_nic(v) }.compact.inject({}) do |acc, obj|
|
58
|
-
acc.merge({ obj[0] => obj[1] })
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
# Parses nic data out of a single line of the human readable output
|
63
|
-
# of vm info.
|
64
|
-
#
|
65
|
-
# **This method typically won't be used except internally.**
|
66
|
-
#
|
67
|
-
# @return [Array] First element is nic name, second is data.
|
68
|
-
def parse_nic(raw)
|
69
|
-
return unless raw =~ /^NIC\s(\d):\s+(.+?)$/
|
70
|
-
return if $2.to_s.strip == "disabled"
|
71
|
-
|
72
|
-
data = {}
|
73
|
-
nicname = "nic#{$1}"
|
74
|
-
$2.to_s.split(/,\s+/).each do |raw_property|
|
75
|
-
next unless raw_property =~ /^(.+?):\s+(.+?)$/
|
76
|
-
|
77
|
-
data[$1.downcase.to_sym] = $2.to_s
|
78
|
-
end
|
79
|
-
|
80
|
-
return nicname.to_sym, data
|
81
|
-
end
|
82
|
-
|
83
44
|
# Populates the nic relationship for anything which is related to it.
|
84
45
|
#
|
85
46
|
# **This method typically won't be used except internally.**
|
86
47
|
#
|
87
48
|
# @return [Array<Nic>]
|
88
|
-
def populate_relationship(caller,
|
89
|
-
|
90
|
-
|
91
|
-
relation = []
|
92
|
-
|
93
|
-
counter = 1
|
94
|
-
loop do
|
95
|
-
break unless data["nic#{counter}".to_sym]
|
49
|
+
def populate_relationship(caller, doc)
|
50
|
+
relation = Proxies::Collection.new(caller)
|
96
51
|
|
97
|
-
|
98
|
-
|
99
|
-
nic = new(counter, caller, data.merge({
|
100
|
-
"nictype#{counter}".to_sym => nictype
|
101
|
-
}))
|
102
|
-
relation.push(nic)
|
103
|
-
counter += 1
|
52
|
+
doc.css("Hardware Network Adapter").each do |adapter|
|
53
|
+
relation << new(caller, adapter)
|
104
54
|
end
|
105
55
|
|
106
56
|
relation
|
@@ -121,21 +71,32 @@ module VirtualBox
|
|
121
71
|
# Since there is currently no way to create a _new_ nic, this is
|
122
72
|
# only used internally. Developers should NOT try to initialize their
|
123
73
|
# own nic objects.
|
124
|
-
def initialize(
|
74
|
+
def initialize(caller, data)
|
125
75
|
super()
|
126
76
|
|
127
|
-
@index =
|
77
|
+
@index = data["slot"].to_i + 1
|
78
|
+
|
79
|
+
# Set the parent
|
80
|
+
write_attribute(:parent, caller)
|
81
|
+
|
82
|
+
# Convert each attribute value to a string
|
83
|
+
attrs = {}
|
84
|
+
data.attributes.each do |key, value|
|
85
|
+
attrs[key] = value.to_s
|
86
|
+
end
|
87
|
+
|
88
|
+
populate_attributes(attrs)
|
128
89
|
|
129
|
-
#
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
90
|
+
# The `nic` attribute is a bit more complicated, but not by
|
91
|
+
# much
|
92
|
+
if data["enabled"] == "true"
|
93
|
+
write_attribute(:nic, data.children[1].name.downcase)
|
94
|
+
else
|
95
|
+
write_attribute(:nic, "none")
|
134
96
|
end
|
135
97
|
|
136
|
-
|
137
|
-
|
138
|
-
}))
|
98
|
+
# Clear dirtiness
|
99
|
+
clear_dirty!
|
139
100
|
end
|
140
101
|
|
141
102
|
# Saves a single attribute of the nic. This method is automatically
|