virtualbox 0.4.1 → 0.4.2
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/Readme.md +9 -9
- data/VERSION +1 -1
- data/docs/GettingStarted.md +11 -11
- data/docs/WhatsNew.md +1 -1
- data/lib/virtualbox.rb +10 -1
- data/lib/virtualbox/abstract_model.rb +47 -29
- data/lib/virtualbox/abstract_model/attributable.rb +16 -16
- data/lib/virtualbox/abstract_model/dirty.rb +10 -10
- data/lib/virtualbox/abstract_model/relatable.rb +22 -22
- data/lib/virtualbox/abstract_model/validatable.rb +4 -4
- data/lib/virtualbox/attached_device.rb +23 -23
- data/lib/virtualbox/command.rb +9 -9
- data/lib/virtualbox/dvd.rb +7 -7
- data/lib/virtualbox/ext/subclass_listing.rb +1 -1
- data/lib/virtualbox/extra_data.rb +17 -17
- data/lib/virtualbox/forwarded_port.rb +23 -23
- data/lib/virtualbox/hard_drive.rb +27 -27
- data/lib/virtualbox/image.rb +25 -18
- data/lib/virtualbox/nic.rb +22 -22
- data/lib/virtualbox/proxies/collection.rb +4 -4
- data/lib/virtualbox/shared_folder.rb +25 -25
- data/lib/virtualbox/storage_controller.rb +16 -16
- data/lib/virtualbox/vm.rb +95 -42
- data/test/virtualbox/abstract_model/attributable_test.rb +28 -28
- data/test/virtualbox/abstract_model/dirty_test.rb +13 -13
- data/test/virtualbox/abstract_model/relatable_test.rb +36 -36
- data/test/virtualbox/abstract_model/validatable_test.rb +22 -22
- data/test/virtualbox/abstract_model_test.rb +46 -36
- data/test/virtualbox/attached_device_test.rb +47 -47
- data/test/virtualbox/command_test.rb +12 -12
- data/test/virtualbox/dvd_test.rb +15 -19
- data/test/virtualbox/ext/subclass_listing_test.rb +2 -2
- data/test/virtualbox/extra_data_test.rb +37 -37
- data/test/virtualbox/forwarded_port_test.rb +31 -31
- data/test/virtualbox/hard_drive_test.rb +40 -48
- data/test/virtualbox/image_test.rb +36 -33
- data/test/virtualbox/nic_test.rb +22 -22
- data/test/virtualbox/proxies/collection_test.rb +6 -6
- data/test/virtualbox/shared_folder_test.rb +36 -36
- data/test/virtualbox/storage_controller_test.rb +14 -14
- data/test/virtualbox/vm_test.rb +121 -70
- data/test/virtualbox_test.rb +19 -0
- data/virtualbox.gemspec +5 -3
- metadata +4 -2
data/lib/virtualbox/dvd.rb
CHANGED
@@ -10,7 +10,7 @@ module VirtualBox
|
|
10
10
|
# DVD.all
|
11
11
|
#
|
12
12
|
# # Empty Drives
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# Sometimes it is useful to have an empty drive. This is the case where you
|
15
15
|
# may have a DVD drive but it has no disk in it. To create an {AttachedDevice},
|
16
16
|
# an image _must_ be specified, and an empty drive is a simple option. Creating
|
@@ -25,7 +25,7 @@ module VirtualBox
|
|
25
25
|
raw = Command.vboxmanage("list dvds")
|
26
26
|
parse_raw(raw)
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
# Returns an empty drive. This is useful for creating new
|
30
30
|
# or modifyingn existing {AttachedDevice} objects and
|
31
31
|
# attaching an empty drive to them.
|
@@ -35,7 +35,7 @@ module VirtualBox
|
|
35
35
|
new(:empty_drive)
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
def initialize(*args)
|
40
40
|
if args.length == 1 && args[0] == :empty_drive
|
41
41
|
@empty_drive = true
|
@@ -43,7 +43,7 @@ module VirtualBox
|
|
43
43
|
super
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
# Override of {Image#empty_drive?}. This will only be true if
|
48
48
|
# the DVD was created with {DVD.empty_drive}.
|
49
49
|
#
|
@@ -51,12 +51,12 @@ module VirtualBox
|
|
51
51
|
def empty_drive?
|
52
52
|
@empty_drive || false
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
# Override of {Image#image_type}.
|
56
56
|
def image_type
|
57
57
|
"dvddrive"
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
# Deletes the DVD from VBox managed list and also from disk.
|
61
61
|
# This method will fail if the disk is currently mounted to any
|
62
62
|
# virtual machine. This method also does nothing for empty drives
|
@@ -68,7 +68,7 @@ module VirtualBox
|
|
68
68
|
# @return [Boolean] True if command was successful, false otherwise.
|
69
69
|
def destroy(raise_errors=false)
|
70
70
|
return false if empty_drive?
|
71
|
-
|
71
|
+
|
72
72
|
Command.vboxmanage("closemedium dvd #{uuid} --delete")
|
73
73
|
true
|
74
74
|
rescue Exceptions::CommandFailedException
|
@@ -7,7 +7,7 @@ module VirtualBox
|
|
7
7
|
#
|
8
8
|
# # Extra Data on a Virtual Machine
|
9
9
|
#
|
10
|
-
# Setting extra data on a virtual machine is easy. All {VM} objects have a
|
10
|
+
# Setting extra data on a virtual machine is easy. All {VM} objects have a
|
11
11
|
# `extra_data` relationship which is just a simple ruby hash, so you can treat
|
12
12
|
# it like one! Once the data is set, simply saving the VM will save the
|
13
13
|
# extra data. An example below:
|
@@ -33,11 +33,11 @@ module VirtualBox
|
|
33
33
|
#
|
34
34
|
class ExtraData < Hash
|
35
35
|
include AbstractModel::Dirty
|
36
|
-
|
36
|
+
|
37
37
|
attr_accessor :parent
|
38
|
-
|
38
|
+
|
39
39
|
@@global_data = nil
|
40
|
-
|
40
|
+
|
41
41
|
class <<self
|
42
42
|
# Gets the global extra data. This will "cache" the data for
|
43
43
|
# future use unless you set the `reload` paramter to true.
|
@@ -49,10 +49,10 @@ module VirtualBox
|
|
49
49
|
raw = Command.vboxmanage("getextradata global enumerate")
|
50
50
|
@@global_data = parse_kv_pairs(raw)
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
@@global_data
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
# Parses the key-value pairs from the extra data enumerated
|
57
57
|
# output.
|
58
58
|
#
|
@@ -64,11 +64,11 @@ module VirtualBox
|
|
64
64
|
next unless line =~ /^Key: (.+?), Value: (.+?)$/i
|
65
65
|
data[$1.to_s] = $2.strip.to_s
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
data.clear_dirty!
|
69
69
|
data
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
# Populates a relationship with another model.
|
73
73
|
#
|
74
74
|
# **This method typically won't be used except internally.**
|
@@ -78,7 +78,7 @@ module VirtualBox
|
|
78
78
|
raw = Command.vboxmanage("getextradata #{Command.shell_escape(caller.name)} enumerate")
|
79
79
|
parse_kv_pairs(raw, caller)
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
# Saves the relationship. This simply calls {#save} on every
|
83
83
|
# member of the relationship.
|
84
84
|
#
|
@@ -87,21 +87,21 @@ module VirtualBox
|
|
87
87
|
data.save
|
88
88
|
end
|
89
89
|
end
|
90
|
-
|
91
|
-
# Initializes an extra data object.
|
90
|
+
|
91
|
+
# Initializes an extra data object.
|
92
92
|
#
|
93
93
|
# @param [Hash] data Initial attributes to populate.
|
94
94
|
def initialize(parent=nil)
|
95
95
|
@parent = parent || "global"
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
# Set an extradata key-value pair. Overrides ruby hash implementation
|
99
99
|
# to set dirty state. Otherwise that, behaves the same way.
|
100
100
|
def []=(key,value)
|
101
101
|
set_dirty!(key, self[key], value)
|
102
102
|
super
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
# Special accessor for parent name attribute. This returns
|
106
106
|
# either the parent name if its a VM object, otherwise
|
107
107
|
# just returns the default.
|
@@ -114,7 +114,7 @@ module VirtualBox
|
|
114
114
|
parent
|
115
115
|
end
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
# Saves extra data. This method does the same thing for both new
|
119
119
|
# and existing extra data, since virtualbox will overwrite old data or
|
120
120
|
# create it if it doesn't exist.
|
@@ -127,14 +127,14 @@ module VirtualBox
|
|
127
127
|
Command.vboxmanage("setextradata #{Command.shell_escape(parent_name)} #{Command.shell_escape(key)} #{Command.shell_escape(value[1])}")
|
128
128
|
clear_dirty!(key)
|
129
129
|
end
|
130
|
-
|
130
|
+
|
131
131
|
true
|
132
132
|
rescue Exceptions::CommandFailedException
|
133
133
|
raise if raise_errors
|
134
134
|
false
|
135
135
|
end
|
136
|
-
|
137
|
-
# Deletes the extra data.
|
136
|
+
|
137
|
+
# Deletes the extra data.
|
138
138
|
#
|
139
139
|
# @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
|
140
140
|
# will be raised if the command failed.
|
@@ -3,7 +3,7 @@ module VirtualBox
|
|
3
3
|
# own private router for all virtual machines. Because of this,
|
4
4
|
# the host machine can't access services within the guest machine.
|
5
5
|
# To get around this, NAT supports port forwarding, which allows the
|
6
|
-
# guest machine services to be forwarded to some port on the host
|
6
|
+
# guest machine services to be forwarded to some port on the host
|
7
7
|
# machine. Port forwarding is done completely through {ExtraData}, but
|
8
8
|
# is a complicated enough procedure that this class was made to
|
9
9
|
# faciliate it.
|
@@ -43,7 +43,7 @@ module VirtualBox
|
|
43
43
|
#
|
44
44
|
# Properties of the model are exposed using standard ruby instance
|
45
45
|
# methods which are generated on the fly. Because of this, they are not listed
|
46
|
-
# below as available instance methods.
|
46
|
+
# below as available instance methods.
|
47
47
|
#
|
48
48
|
# These attributes can be accessed and modified via standard ruby-style
|
49
49
|
# `instance.attribute` and `instance.attribute=` methods. The attributes are
|
@@ -74,7 +74,7 @@ module VirtualBox
|
|
74
74
|
attribute :protocol, :default => "TCP"
|
75
75
|
attribute :guestport
|
76
76
|
attribute :hostport
|
77
|
-
|
77
|
+
|
78
78
|
class <<self
|
79
79
|
# Populates a relationship with another model.
|
80
80
|
#
|
@@ -83,10 +83,10 @@ module VirtualBox
|
|
83
83
|
# @return [Array<ForwardedPort>]
|
84
84
|
def populate_relationship(caller, data)
|
85
85
|
relation = Proxies::Collection.new(caller)
|
86
|
-
|
86
|
+
|
87
87
|
caller.extra_data.each do |key, value|
|
88
88
|
next unless key =~ /^(VBoxInternal\/Devices\/(.+?)\/(.+?)\/LUN#0\/Config\/(.+?)\/)Protocol$/i
|
89
|
-
|
89
|
+
|
90
90
|
port = new({
|
91
91
|
:parent => caller,
|
92
92
|
:name => $4.to_s,
|
@@ -96,15 +96,15 @@ module VirtualBox
|
|
96
96
|
:guestport => caller.extra_data["#{$1.to_s}GuestPort"],
|
97
97
|
:hostport => caller.extra_data["#{$1.to_s}HostPort"]
|
98
98
|
})
|
99
|
-
|
99
|
+
|
100
100
|
port.existing_record!
|
101
|
-
|
101
|
+
|
102
102
|
relation.push(port)
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
relation
|
106
106
|
end
|
107
|
-
|
107
|
+
|
108
108
|
# Saves the relationship. This simply calls {#save} on every
|
109
109
|
# member of the relationship.
|
110
110
|
#
|
@@ -115,23 +115,23 @@ module VirtualBox
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
end
|
118
|
-
|
118
|
+
|
119
119
|
# @param [Hash] data The initial attributes to populate.
|
120
120
|
def initialize(data={})
|
121
121
|
super()
|
122
122
|
populate_attributes(data)
|
123
123
|
end
|
124
|
-
|
124
|
+
|
125
125
|
# Validates a forwarded port.
|
126
126
|
def validate
|
127
127
|
super
|
128
|
-
|
128
|
+
|
129
129
|
validates_presence_of :parent
|
130
130
|
validates_presence_of :name
|
131
131
|
validates_presence_of :guestport
|
132
132
|
validates_presence_of :hostport
|
133
133
|
end
|
134
|
-
|
134
|
+
|
135
135
|
# Saves the forwarded port.
|
136
136
|
#
|
137
137
|
# @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
|
@@ -139,25 +139,25 @@ module VirtualBox
|
|
139
139
|
# @return [Boolean] True if command was successful, false otherwise.
|
140
140
|
def save(raise_errors=false)
|
141
141
|
return true if !new_record? && !changed?
|
142
|
-
|
142
|
+
|
143
143
|
if !valid?
|
144
144
|
raise Exceptions::ValidationFailedException.new(errors) if raise_errors
|
145
145
|
return false
|
146
146
|
end
|
147
|
-
|
147
|
+
|
148
148
|
destroy(raise_errors) if name_changed?
|
149
|
-
|
149
|
+
|
150
150
|
parent.extra_data["#{key_prefix}Protocol"] = protocol
|
151
151
|
parent.extra_data["#{key_prefix}GuestPort"] = guestport
|
152
152
|
parent.extra_data["#{key_prefix}HostPort"] = hostport
|
153
153
|
result = parent.extra_data.save(raise_errors)
|
154
|
-
|
154
|
+
|
155
155
|
clear_dirty!
|
156
156
|
existing_record!
|
157
|
-
|
157
|
+
|
158
158
|
result
|
159
159
|
end
|
160
|
-
|
160
|
+
|
161
161
|
# Destroys the port forwarding mapping.
|
162
162
|
#
|
163
163
|
# @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
|
@@ -170,19 +170,19 @@ module VirtualBox
|
|
170
170
|
results << parent.extra_data.delete("#{key_prefix(true)}Protocol", raise_errors)
|
171
171
|
results << parent.extra_data.delete("#{key_prefix(true)}GuestPort", raise_errors)
|
172
172
|
results << parent.extra_data.delete("#{key_prefix(true)}HostPort", raise_errors)
|
173
|
-
|
173
|
+
|
174
174
|
new_record!
|
175
175
|
end
|
176
|
-
|
176
|
+
|
177
177
|
results.empty? || results.all? { |o| o == true }
|
178
178
|
end
|
179
|
-
|
179
|
+
|
180
180
|
# Relationship callback when added to a collection. This is automatically
|
181
181
|
# called by any relationship collection when this object is added.
|
182
182
|
def added_to_relationship(parent)
|
183
183
|
write_attribute(:parent, parent)
|
184
184
|
end
|
185
|
-
|
185
|
+
|
186
186
|
# Returns the prefix to be used for the extra data key. Forwarded ports
|
187
187
|
# are created by simply setting {ExtraData} on a {VM}. This class hides most
|
188
188
|
# of the inner workings of it, but it requires a common prefix. This method
|
@@ -7,7 +7,7 @@ module VirtualBox
|
|
7
7
|
# find all or a specific hard drive, respectively. Example below:
|
8
8
|
#
|
9
9
|
# VirtualBox::HardDrive.all
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Or:
|
12
12
|
#
|
13
13
|
# VirtualBox::HardDrive.find("Foo.vdi")
|
@@ -49,9 +49,9 @@ module VirtualBox
|
|
49
49
|
# # Cloning Hard Drives
|
50
50
|
#
|
51
51
|
# Hard drives can just as easily be cloned as they can be created or destroyed.
|
52
|
-
#
|
52
|
+
#
|
53
53
|
# hd = VirtualBox::HardDrive.find("foo")
|
54
|
-
# cloned_hd = hd.clone("bar")
|
54
|
+
# cloned_hd = hd.clone("bar")
|
55
55
|
#
|
56
56
|
# In addition to simply cloning hard drives, this command can be used to
|
57
57
|
# clone to a different format:
|
@@ -63,13 +63,13 @@ module VirtualBox
|
|
63
63
|
#
|
64
64
|
# Properties of the model are exposed using standard ruby instance
|
65
65
|
# methods which are generated on the fly. Because of this, they are not listed
|
66
|
-
# below as available instance methods.
|
66
|
+
# below as available instance methods.
|
67
67
|
#
|
68
68
|
# These attributes can be accessed and modified via standard ruby-style
|
69
69
|
# `instance.attribute` and `instance.attribute=` methods. The attributes are
|
70
70
|
# listed below. If you aren't sure what this means or you can't understand
|
71
71
|
# why the below is listed, please read {Attributable}.
|
72
|
-
#
|
72
|
+
#
|
73
73
|
# attribute :uuid, :readonly => true
|
74
74
|
# attribute :location
|
75
75
|
# attribute :accessible, :readonly => true
|
@@ -79,7 +79,7 @@ module VirtualBox
|
|
79
79
|
class HardDrive < Image
|
80
80
|
attribute :format, :default => "VDI"
|
81
81
|
attribute :size
|
82
|
-
|
82
|
+
|
83
83
|
class <<self
|
84
84
|
# Returns an array of all available hard drives as HardDrive
|
85
85
|
# objects.
|
@@ -89,30 +89,30 @@ module VirtualBox
|
|
89
89
|
raw = Command.vboxmanage("list hdds")
|
90
90
|
parse_blocks(raw).collect { |v| find(v[:uuid]) }
|
91
91
|
end
|
92
|
-
|
92
|
+
|
93
93
|
# Finds one specific hard drive by UUID or file name. If the
|
94
94
|
# hard drive can not be found, will return `nil`.
|
95
95
|
#
|
96
96
|
# @return [HardDrive]
|
97
97
|
def find(id)
|
98
98
|
raw = Command.vboxmanage("showhdinfo #{id}")
|
99
|
-
|
99
|
+
|
100
100
|
# Return nil if the hard drive doesn't exist
|
101
101
|
return nil if raw =~ /VERR_FILE_NOT_FOUND/
|
102
|
-
|
102
|
+
|
103
103
|
data = raw.split(/\n\n/).collect { |v| parse_block(v) }.find { |v| !v.nil? }
|
104
|
-
|
104
|
+
|
105
105
|
# Set equivalent fields
|
106
106
|
data[:format] = data[:"storage format"]
|
107
107
|
data[:size] = data[:"logical size"].split(/\s+/)[0] if data.has_key?(:"logical size")
|
108
|
-
|
108
|
+
|
109
109
|
# Return new object
|
110
110
|
new(data)
|
111
111
|
end
|
112
112
|
end
|
113
|
-
|
113
|
+
|
114
114
|
# Clone hard drive, possibly also converting formats. All formats
|
115
|
-
# supported by your local VirtualBox installation are supported
|
115
|
+
# supported by your local VirtualBox installation are supported
|
116
116
|
# here. If no format is specified, the format of the source drive
|
117
117
|
# will be used.
|
118
118
|
#
|
@@ -126,27 +126,27 @@ module VirtualBox
|
|
126
126
|
def clone(outputfile, format="VDI", raise_errors=false)
|
127
127
|
raw = Command.vboxmanage("clonehd #{uuid} #{Command.shell_escape(outputfile)} --format #{format} --remember")
|
128
128
|
return nil unless raw =~ /UUID: (.+?)$/
|
129
|
-
|
129
|
+
|
130
130
|
self.class.find($1.to_s)
|
131
131
|
rescue Exceptions::CommandFailedException
|
132
132
|
raise if raise_errors
|
133
133
|
nil
|
134
134
|
end
|
135
|
-
|
135
|
+
|
136
136
|
# Override of {Image#image_type}.
|
137
137
|
def image_type
|
138
138
|
"hdd"
|
139
139
|
end
|
140
|
-
|
140
|
+
|
141
141
|
# Validates a hard drive.
|
142
142
|
def validate
|
143
143
|
super
|
144
|
-
|
144
|
+
|
145
145
|
validates_presence_of :format
|
146
146
|
validates_presence_of :size
|
147
147
|
end
|
148
|
-
|
149
|
-
# Creates a new hard drive.
|
148
|
+
|
149
|
+
# Creates a new hard drive.
|
150
150
|
#
|
151
151
|
# **This method should NEVER be called. Call {#save} instead.**
|
152
152
|
#
|
@@ -158,25 +158,25 @@ module VirtualBox
|
|
158
158
|
raise Exceptions::ValidationFailedException.new(errors) if raise_errors
|
159
159
|
return false
|
160
160
|
end
|
161
|
-
|
161
|
+
|
162
162
|
raw = Command.vboxmanage("createhd --filename #{location} --size #{size} --format #{read_attribute(:format)} --remember")
|
163
163
|
return nil unless raw =~ /UUID: (.+?)$/
|
164
|
-
|
164
|
+
|
165
165
|
# Just replace our attributes with the newly created ones. This also
|
166
166
|
# will set new_record to false.
|
167
167
|
populate_attributes(self.class.find($1.to_s).attributes)
|
168
|
-
|
168
|
+
|
169
169
|
# Return the success of the command
|
170
170
|
true
|
171
171
|
rescue Exceptions::CommandFailedException
|
172
172
|
raise if raise_errors
|
173
173
|
false
|
174
174
|
end
|
175
|
-
|
175
|
+
|
176
176
|
# Saves the hard drive object. If the hard drive is new,
|
177
177
|
# this will create a new hard drive. Otherwise, it will
|
178
178
|
# save any other details about the existing hard drive.
|
179
|
-
#
|
179
|
+
#
|
180
180
|
# Currently, **saving existing hard drives does nothing**.
|
181
181
|
# This is a limitation of VirtualBox, rather than the library itself.
|
182
182
|
#
|
@@ -191,10 +191,10 @@ module VirtualBox
|
|
191
191
|
super
|
192
192
|
end
|
193
193
|
end
|
194
|
-
|
194
|
+
|
195
195
|
# Destroys the hard drive. This deletes the hard drive off
|
196
|
-
# of disk.
|
197
|
-
#
|
196
|
+
# of disk.
|
197
|
+
#
|
198
198
|
# **This operation is not reversable.**
|
199
199
|
#
|
200
200
|
# @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
|