virtualbox 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- 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}
|