Class: VirtualBox::ForwardedPort
- Inherits:
-
AbstractModel
- Object
- AbstractModel
- VirtualBox::ForwardedPort
- Defined in:
- lib/virtualbox/forwarded_port.rb
Overview
When a VM uses NAT as its NIC type, VirtualBox acts like its own private router for all virtual machines. Because of this, the host machine can’t access services within the guest machine. To get around this, NAT supports port forwarding, which allows the guest machine services to be forwarded to some port on the host machine. Port forwarding is done completely through ExtraData, but is a complicated enough procedure that this class was made to faciliate it.
Note: After changing any forwarded ports, the entire VirtualBox process must be restarted completely for them to take effect. When working with the ruby library, this isn’t so much of an issue, but if you have any VMs running, they must all be shut down and restarted.
# Adding a new Forwarded Port
Since forwarded ports rely on being part of a VM, we’re going to assume that ‘vm` points to a VM which has already been found.
port = VirtualBox::ForwardedPort.new
port.name = "apache" # This can be anything
port.guestport = 80
port.hostport = 8080
vm.forwarded_ports << port
port.save # Or vm.save
# Modifying an Existing Forwarded Port
This is assuming that ‘vm` is a local variable storing a VM object which has already been found.
vm.forwarded_ports.first.hostport = 1919
vm.save
# Deleting a Forwarded Port
To delete a forwarded port, you simply destroy it like any other model:
vm.forwarded_ports.first.destroy
# Attributes and Relationships
Properties of the model are exposed using standard ruby instance methods which are generated on the fly. Because of this, they are not listed below as available instance methods.
These attributes can be accessed and modified via standard ruby-style ‘instance.attribute` and `instance.attribute=` methods. The attributes are listed below.
Relationships are also accessed like attributes but can’t be set. Instead, they are typically references to other objects such as an AttachedDevice which in turn have their own attributes which can be modified.
## Attributes
This is copied directly from the class header, but lists all available attributes. If you don’t understand what this means, read AbstractModel::Attributable.
attribute :parent, :readonly => true
attribute :name
attribute :instance, :default => "0"
attribute :device, :default => "pcnet"
attribute :protocol, :default => "TCP"
attribute :guestport
attribute :hostport
Class Method Summary collapse
-
.populate_relationship(caller, data) ⇒ Array<ForwardedPort>
Populates a relationship with another model.
-
.save_relationship(caller, data) ⇒ Object
Saves the relationship.
Instance Method Summary collapse
-
#added_to_relationship(proxy) ⇒ Object
Relationship callback when added to a collection.
-
#destroy ⇒ Boolean
Destroys the port forwarding mapping.
-
#device ⇒ String
Retrieves the device for the forwarded port.
-
#initialize(data = {}) ⇒ ForwardedPort
constructor
A new instance of ForwardedPort.
-
#key_prefix(old_name = false) ⇒ String
Returns the prefix to be used for the extra data key.
-
#save ⇒ Boolean
Saves the forwarded port.
-
#validate ⇒ Object
Validates a forwarded port.
Methods inherited from AbstractModel
#errors, errors_for_relationship, #existing_record!, #inspect, #lazy_attribute?, #lazy_relationship?, #new_record!, #new_record?, #parent_machine, #populate_attributes, #populate_relationship, #populate_relationships, reload!, #reload!, reload?, reloaded!, #save!, #save_attribute, #save_changed_interface_attributes, #save_interface_attribute, #set_relationship, #write_attribute
Methods included from AbstractModel::Validatable
#__validates_extract_options, #add_error, #clear_errors, #errors, #errors_on, #full_error_messages, #valid?, #validates_format_of, #validates_inclusion_of, #validates_numericality_of, #validates_presence_of
Methods included from AbstractModel::Relatable
#destroy_relationship, #destroy_relationships, #has_relationship?, included, #lazy_relationship?, #loaded_relationship?, #populate_relationship, #populate_relationships, #read_relationship, #relationship_class, #relationship_data, #save_relationship, #save_relationships, #set_relationship
Methods included from AbstractModel::VersionMatcher
#assert_version_match, #split_version, #version_match?
Methods included from AbstractModel::Dirty
#changed?, #changes, #clear_dirty!, #ignore_dirty, #method_missing, #set_dirty!
Methods included from AbstractModel::InterfaceAttributes
#load_interface_attribute, #load_interface_attributes, #save_interface_attribute, #save_interface_attributes, #spec_to_proc
Methods included from AbstractModel::Attributable
#attributes, #has_attribute?, included, #lazy_attribute?, #loaded_attribute?, #populate_attributes, #read_attribute, #readonly_attribute?, #write_attribute
Methods included from Logger
included, #logger, #logger_output=
Constructor Details
#initialize(data = {}) ⇒ ForwardedPort
Returns a new instance of ForwardedPort.
122 123 124 125 |
# File 'lib/virtualbox/forwarded_port.rb', line 122 def initialize(data={}) super() populate_attributes(data) if !data.empty? end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class VirtualBox::AbstractModel::Dirty
Class Method Details
.populate_relationship(caller, data) ⇒ Array<ForwardedPort>
Populates a relationship with another model.
**This method typically won’t be used except internally.**
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/virtualbox/forwarded_port.rb', line 85 def populate_relationship(caller, data) relation = Proxies::Collection.new(caller) caller.extra_data.each do |key, value| next unless key =~ /^(VBoxInternal\/Devices\/(.+?)\/(.+?)\/LUN#0\/Config\/(.+?)\/)Protocol$/i port = new({ :parent => caller, :parent_collection => relation, :name => $4.to_s, :instance => $3.to_s, :device => $2.to_s, :protocol => value, :guestport => caller.extra_data["#{$1.to_s}GuestPort"], :hostport => caller.extra_data["#{$1.to_s}HostPort"] }) port.existing_record! relation.push(port) end relation end |
.save_relationship(caller, data) ⇒ Object
Saves the relationship. This simply calls #save on every member of the relationship.
**This method typically won’t be used except internally.**
114 115 116 117 118 |
# File 'lib/virtualbox/forwarded_port.rb', line 114 def save_relationship(caller, data) data.dup.each do |fp| fp.save end end |
Instance Method Details
#added_to_relationship(proxy) ⇒ Object
Relationship callback when added to a collection. This is automatically called by any relationship collection when this object is added.
206 207 208 209 |
# File 'lib/virtualbox/forwarded_port.rb', line 206 def added_to_relationship(proxy) write_attribute(:parent, proxy.parent) write_attribute(:parent_collection, proxy) end |
#destroy ⇒ Boolean
Destroys the port forwarding mapping.
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/virtualbox/forwarded_port.rb', line 187 def destroy results = [] if !new_record? results << parent.extra_data.delete("#{key_prefix(true)}Protocol") results << parent.extra_data.delete("#{key_prefix(true)}GuestPort") results << parent.extra_data.delete("#{key_prefix(true)}HostPort") # Remove it from any collection parent_collection.delete(self, true) if parent_collection new_record! end results.empty? || results.all? { |o| o == true } end |
#device ⇒ String
Retrieves the device for the forwarded port. This tries to “do the right thing” depending on the first NIC of the VM parent by either setting the forwarded port type to “pcnet” or “e1000.” If the device was already set manually, this method will simply return that value instead.
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/virtualbox/forwarded_port.rb', line 144 def device # Return the current or default value if it is: # * an existing record, since it was already mucked with, no need to # modify it again # * device setting changed, since we should return what the user set # it to # * If the parent is nil, since we can't infer the type without a parent return read_attribute(:device) if !new_record? || device_changed? || parent.nil? device_map = { :Am79C970A => "pcnet", :Am79C973 => "pcnet", :I82540EM => "e1000", :I82543GC => "e1000", :I82545EM => "e1000" } return device_map[parent.network_adapters[0].adapter_type] end |
#key_prefix(old_name = false) ⇒ String
217 218 219 220 |
# File 'lib/virtualbox/forwarded_port.rb', line 217 def key_prefix(old_name=false) name_value = old_name && name_changed? ? name_was : name "VBoxInternal\/Devices\/#{device}\/#{instance}\/LUN#0\/Config\/#{name_value}\/" end |
#save ⇒ Boolean
Saves the forwarded port.
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/virtualbox/forwarded_port.rb', line 167 def save return true if !new_record? && !changed? raise Exceptions::ValidationFailedException.new(errors) if !valid? destroy if !new_record? && name_changed? parent.extra_data["#{key_prefix}Protocol"] = protocol parent.extra_data["#{key_prefix}GuestPort"] = guestport parent.extra_data["#{key_prefix}HostPort"] = hostport result = parent.extra_data.save clear_dirty! existing_record! result end |
#validate ⇒ Object
Validates a forwarded port.
128 129 130 131 132 133 134 135 |
# File 'lib/virtualbox/forwarded_port.rb', line 128 def validate super validates_presence_of :parent validates_presence_of :name validates_presence_of :guestport validates_presence_of :hostport end |