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.
Files changed (44) hide show
  1. data/Readme.md +9 -9
  2. data/VERSION +1 -1
  3. data/docs/GettingStarted.md +11 -11
  4. data/docs/WhatsNew.md +1 -1
  5. data/lib/virtualbox.rb +10 -1
  6. data/lib/virtualbox/abstract_model.rb +47 -29
  7. data/lib/virtualbox/abstract_model/attributable.rb +16 -16
  8. data/lib/virtualbox/abstract_model/dirty.rb +10 -10
  9. data/lib/virtualbox/abstract_model/relatable.rb +22 -22
  10. data/lib/virtualbox/abstract_model/validatable.rb +4 -4
  11. data/lib/virtualbox/attached_device.rb +23 -23
  12. data/lib/virtualbox/command.rb +9 -9
  13. data/lib/virtualbox/dvd.rb +7 -7
  14. data/lib/virtualbox/ext/subclass_listing.rb +1 -1
  15. data/lib/virtualbox/extra_data.rb +17 -17
  16. data/lib/virtualbox/forwarded_port.rb +23 -23
  17. data/lib/virtualbox/hard_drive.rb +27 -27
  18. data/lib/virtualbox/image.rb +25 -18
  19. data/lib/virtualbox/nic.rb +22 -22
  20. data/lib/virtualbox/proxies/collection.rb +4 -4
  21. data/lib/virtualbox/shared_folder.rb +25 -25
  22. data/lib/virtualbox/storage_controller.rb +16 -16
  23. data/lib/virtualbox/vm.rb +95 -42
  24. data/test/virtualbox/abstract_model/attributable_test.rb +28 -28
  25. data/test/virtualbox/abstract_model/dirty_test.rb +13 -13
  26. data/test/virtualbox/abstract_model/relatable_test.rb +36 -36
  27. data/test/virtualbox/abstract_model/validatable_test.rb +22 -22
  28. data/test/virtualbox/abstract_model_test.rb +46 -36
  29. data/test/virtualbox/attached_device_test.rb +47 -47
  30. data/test/virtualbox/command_test.rb +12 -12
  31. data/test/virtualbox/dvd_test.rb +15 -19
  32. data/test/virtualbox/ext/subclass_listing_test.rb +2 -2
  33. data/test/virtualbox/extra_data_test.rb +37 -37
  34. data/test/virtualbox/forwarded_port_test.rb +31 -31
  35. data/test/virtualbox/hard_drive_test.rb +40 -48
  36. data/test/virtualbox/image_test.rb +36 -33
  37. data/test/virtualbox/nic_test.rb +22 -22
  38. data/test/virtualbox/proxies/collection_test.rb +6 -6
  39. data/test/virtualbox/shared_folder_test.rb +36 -36
  40. data/test/virtualbox/storage_controller_test.rb +14 -14
  41. data/test/virtualbox/vm_test.rb +121 -70
  42. data/test/virtualbox_test.rb +19 -0
  43. data/virtualbox.gemspec +5 -3
  44. metadata +4 -2
@@ -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
@@ -3,7 +3,7 @@ module VirtualBox::SubclassListing
3
3
  def self.included(base)
4
4
  base.extend ClassMethods
5
5
  end
6
-
6
+
7
7
  module ClassMethods
8
8
  def subclasses(direct = false)
9
9
  classes = []
@@ -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}