1 | #!/usr/bin/python
|
---|
2 |
|
---|
3 | """
|
---|
4 | Copyright (C) 2009-2022 Oracle and/or its affiliates.
|
---|
5 |
|
---|
6 | This file is part of VirtualBox base platform packages, as
|
---|
7 | available from https://www.virtualbox.org.
|
---|
8 |
|
---|
9 | This program is free software; you can redistribute it and/or
|
---|
10 | modify it under the terms of the GNU General Public License
|
---|
11 | as published by the Free Software Foundation, in version 3 of the
|
---|
12 | License.
|
---|
13 |
|
---|
14 | This program is distributed in the hope that it will be useful, but
|
---|
15 | WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
17 | General Public License for more details.
|
---|
18 |
|
---|
19 | You should have received a copy of the GNU General Public License
|
---|
20 | along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
21 |
|
---|
22 | SPDX-License-Identifier: GPL-3.0-only
|
---|
23 | """
|
---|
24 |
|
---|
25 | #################################################################################
|
---|
26 | # This program is a port-forwarding configurator supposed to simplify
|
---|
27 | # port-forwarding for NAT users
|
---|
28 | # > python VBoxPortForwarding.py --vm winXP -a 1 -p TCP -l 8080 -g 80 -P www
|
---|
29 | # generates sequence of API calls, equivalent to:
|
---|
30 | # > VBoxManage setextradata "winXP"
|
---|
31 | # "VBoxInternal/Devices/pcnet/0/LUN#0/Config/www/Protocol" TCP
|
---|
32 | # > VBoxManage setextradata "winXP"
|
---|
33 | # "VBoxInternal/Devices/pcnet/0/LUN#0/Config/www/GuestPort" 80
|
---|
34 | # > VBoxManage setextradata "winXP"
|
---|
35 | # "VBoxInternal/Devices/pcnet/0/LUN#0/Config/www/HostPort" 8080
|
---|
36 | ################################################################################
|
---|
37 |
|
---|
38 | import os,sys
|
---|
39 | from vboxapi import VirtualBoxManager
|
---|
40 | import optparse
|
---|
41 |
|
---|
42 | class OptionParser (optparse.OptionParser):
|
---|
43 | def check_required(self, opt):
|
---|
44 | option = self.get_option(opt)
|
---|
45 | if option.type == "string" and getattr(self.values, option.dest) != None:
|
---|
46 | return True
|
---|
47 | if option.type == "int" and getattr(self.values, option.dest) != -1:
|
---|
48 | return True
|
---|
49 | return False
|
---|
50 |
|
---|
51 | def generate_profile_name(proto, host_port, guest_port):
|
---|
52 | return proto + '_' + str(host_port) + '_' + str(guest_port)
|
---|
53 |
|
---|
54 | def main(argv):
|
---|
55 |
|
---|
56 | usage = "usage: %prog --vm winXP -a 1 -p TCP -l 8080 -g 80 -P www"
|
---|
57 | parser = OptionParser(usage=usage)
|
---|
58 | parser.add_option("-V", "--vm", action="store", dest="vmname", type="string",
|
---|
59 | help="Name or UID of VM to operate on", default=None)
|
---|
60 | parser.add_option("-P", "--profile", dest="profile", type="string",
|
---|
61 | default=None)
|
---|
62 | parser.add_option("-p", "--ip-proto", dest="proto", type="string",
|
---|
63 | default=None)
|
---|
64 | parser.add_option("-l", "--host-port", dest="host_port", type="int",
|
---|
65 | default = -1)
|
---|
66 | parser.add_option("-g", "--guest-port", dest="guest_port", type="int",
|
---|
67 | default = -1)
|
---|
68 | parser.add_option("-a", "--adapter", dest="adapter", type="int",
|
---|
69 | default=-1)
|
---|
70 | (options,args) = parser.parse_args(argv)
|
---|
71 |
|
---|
72 | if (not (parser.check_required("-V") or parser.check_required("-G"))):
|
---|
73 | parser.error("please define --vm or --guid option")
|
---|
74 | if (not parser.check_required("-p")):
|
---|
75 | parser.error("please define -p or --ip-proto option")
|
---|
76 | if (not parser.check_required("-l")):
|
---|
77 | parser.error("please define -l or --host_port option")
|
---|
78 | if (not parser.check_required("-g")):
|
---|
79 | parser.error("please define -g or --guest_port option")
|
---|
80 | if (not parser.check_required("-a")):
|
---|
81 | parser.error("please define -a or --adapter option")
|
---|
82 |
|
---|
83 | man = VirtualBoxManager(None, None)
|
---|
84 | vb = man.getVirtualBox()
|
---|
85 | print "VirtualBox version: %s" % vb.version,
|
---|
86 | print "r%s" % vb.revision
|
---|
87 |
|
---|
88 | vm = None
|
---|
89 | try:
|
---|
90 | if options.vmname != None:
|
---|
91 | vm = vb.findMachine(options.vmname)
|
---|
92 | elif options.vmname != None:
|
---|
93 | vm = vb.getMachine(options.vmname)
|
---|
94 | except:
|
---|
95 | print "can't find VM by name or UID:",options.vmname
|
---|
96 | del man
|
---|
97 | return
|
---|
98 |
|
---|
99 | print "vm found: %s [%s]" % (vm.name, vm.id)
|
---|
100 |
|
---|
101 | session = man.openMachineSession(vm.id)
|
---|
102 | vm = session.machine
|
---|
103 |
|
---|
104 | adapter = vm.getNetworkAdapter(options.adapter)
|
---|
105 |
|
---|
106 | if adapter.enabled == False:
|
---|
107 | print "adapter(%d) is disabled" % adapter.slot
|
---|
108 | del man
|
---|
109 | return
|
---|
110 |
|
---|
111 | name = None
|
---|
112 | if (adapter.adapterType == man.constants.NetworkAdapterType_Null):
|
---|
113 | print "none adapter type detected"
|
---|
114 | return -1
|
---|
115 | elif (adapter.adapterType == man.constants.NetworkAdapterType_Am79C970A):
|
---|
116 | name = "pcnet"
|
---|
117 | elif (adapter.adapterType == man.constants.NetworkAdapterType_Am79C973):
|
---|
118 | name = "pcnet"
|
---|
119 | elif (adapter.adapterType == man.constants.NetworkAdapterType_I82540EM):
|
---|
120 | name = "e1000"
|
---|
121 | elif (adapter.adapterType == man.constants.NetworkAdapterType_I82545EM):
|
---|
122 | name = "e1000"
|
---|
123 | elif (adapter.adapterType == man.constants.NetworkAdapterType_I82543GC):
|
---|
124 | name = "e1000"
|
---|
125 | print "adapter of '%s' type has been detected" % name
|
---|
126 |
|
---|
127 | profile_name = options.profile
|
---|
128 | if profile_name == None:
|
---|
129 | profile_name = generate_profile_name(options.proto.upper(),
|
---|
130 | options.host_port,
|
---|
131 | options.guest_port)
|
---|
132 | config = "VBoxInternal/Devices/" + name + "/"
|
---|
133 | config = config + str(adapter.slot) +"/LUN#0/Config/" + profile_name
|
---|
134 | proto = config + "/Protocol"
|
---|
135 | host_port = config + "/HostPort"
|
---|
136 | guest_port = config + "/GuestPort"
|
---|
137 |
|
---|
138 | vm.setExtraData(proto, options.proto.upper())
|
---|
139 | vm.setExtraData(host_port, str(options.host_port))
|
---|
140 | vm.setExtraData(guest_port, str(options.guest_port))
|
---|
141 |
|
---|
142 |
|
---|
143 | vm.saveSettings()
|
---|
144 | man.closeMachineSession(session)
|
---|
145 |
|
---|
146 | del man
|
---|
147 |
|
---|
148 | if __name__ == "__main__":
|
---|
149 | main(sys.argv)
|
---|