VMware Cloud Community
ZMerLynn
Contributor
Contributor

Virtual Serial Port Concentrator: vSPC.py

I got tired of managing the port mappings for a bunch of VM serial consoles, so I wrote a virtual Serial Port Concentrator based on the publicly available documentation.


I started a project for it here:

  vSPC.py: https://sourceforge.net/p/vspcpy/

It's 2-clause BSD-licensed, as I didn't see much point in GPLing a tool that most people will use internally. As $WORK needs progress, I may make some other additions.

This is all based on public documetation here: http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/vsp41_usingproxy_virtual_serial_ports.pdf

The --help text is hopefully illustrative to its use and my goals:

---

vSPC.py ($Id: 472270bed4e5f6bdd3bbb124e68e8cf744a9a1dc $)
Common options:
vSPC.py: [-h|--help] [-d|--debug] [-a|--admin-port P] -s|--server|hostname
Query (without --server): Connect to the --admin-port (default 13371) on
  the specified host and return a list of VMs. Output is colon
  delimited, vm-name:vm-uuid:port.
Server (with --server):
  Additional options:
    [-p|--proxy-port P] [-r|--port-range-start P] [--vm-expire-time seconds]
    [--stdout] [--no-fork]
  Start Virtual Serial Port Concentrator. By default, vSPC listens on
  port 13370 for VMware virtual serial connections. Each new VM is
  assigned a listener, starting at port 50000. VM to port mappings may be
  queried using vSPC.py without the --server option (e.g. 'vSPC.py localhost').
  A standard 'telnet' may then be used to connect to the VM serial port.
  In order to configure a VM to use the vSPC, you must be running ESXi 4.1+. Add the serial port
  to the VM, then select:
    (*) Use Network
      (*) Server
      Port URI: vSPC.py
      [X] Use Virtual Serial Port Concentrator:
      vSPC: telnet://dispater:13370
  NOTE: Direction MUST be Server, and Port URI MUST be vSPC.py
  vSPC.py makes a best effort to keep VM to port number mappings stable,
  based on the UUID of the connecting VM. Even if a VM disconnects,
  client connections are maintained in anticipation of the VM
  reconnecting (e.g. if the VM is rebooting). The UUID<->port mapping
  is maintained as long as there are either client connections or as
  long as the VM is connected, and even after this condition is no
  longer met, the mapping is retained for --vm-expire-time seconds
  (default 86400).
  Explanation of server options:
    -a|--admin-port: The port to listen/use for queries (default 13371)
    -p|--proxy-port: The proxy port to listen on (default 13370)
    -r|--port-range-start: What port to start port allocations from (default 50000)
    --stdout: Log to stdout instead of syslog
    --no-fork: Don't daemonize
    -d|--debug: Debug mode (turns up logging and implies --stdout --no-fork)

---

I hope you find it useful!

0 Kudos
15 Replies
chilow
Enthusiast
Enthusiast

This is an excellent tool!  Thanks for sharing!  Is there a way to make the VM<->Port assignments permanent and persistent across reboots of the vSPC?  I have noticed that if the vSPC is restarted the VMs don’t automatically register again with the vSPC when it is back online; is this normal?

0 Kudos
ZMerLynn
Contributor
Contributor

I'm glad you find it useful!

I would like to add a persistence feature soon. It's not hard, just needs a little thought and a little time. This is actually a feature desired at work, too, as it solves both the case that you reboot the server and the case where vSPC.py is restarted. Look for this in the next week or two.

A longer project, and not one that we need at $WORK, is for VM-VM mappings without having to know the port number. I was considering doing this by allowing you to specify that it was a "client" with a specific proxy destination that was the UUID of the "server" VM that you wanted to connect to. The only real advantage of VM-VM communication, though, is if you have some application that insists on being a serial client. For our use cases (manual console use, automated console scripting, kernel debugger), a TCP connection is fine.

In regards to your second question.. In my testing with vSphere 5, the VMs would re-register within, say, 30 seconds or so of vSPC.py restarting, so I haven't seen that particular issue. I haven't checked the same behavior on 4.1. You might check the vmware.log for the VM to see if it says anything.

0 Kudos
ZMerLynn
Contributor
Contributor

Persistence has been implemented! Mappings can now be persisted to a file.

After a little more testing at work, I'll probably call this 1.0. Check the website

for more details.

0 Kudos
chilow
Enthusiast
Enthusiast

Thanks! Is there a way to edit the file to assign ports to VMs before they login to the vSPC?

0 Kudos
ZMerLynn
Contributor
Contributor

There's no way to assign a static mapping in the builtin File backend right now. You could probably

implement a hacky workaround by manipulating the File backend's shelf directly.

What is your use case? I could perhaps suggest another way to solve it if I knew the intention.

You can, for instance, use the new backend interface to write your own backend with customized

hooks that would allow you to update an external database upon VM change. You could then even

override the load_vms() function (as vSPCBackendFile does) to load initially from that database

as well.

Ideally you could use the admin port to do this. However, the ability for the admin port to actually

manipulate anything brings up other issues, like authentication. I considered having a read-only

port reasonable, but once you start doing things like forcing VM mappings, or forcibly tearing down

VM or client connections (both of which could be reasonable), it's questionable.

0 Kudos
chilow
Enthusiast
Enthusiast

I thought it would be nice to have the option to statically assign a VM’s UUID to a port on the vSPC.py host in the event that a VM was rebuilt and needed to have the same port on the vSPC.py host or want a certain VM mapped to a certain port. We use a proxy host to send end users to serial consoles of our Linux hosts; the proxy host contains a static file that contains server hostname to serial port concentor IP:port mapping.

Does the command string below look correct? If I reboot the host running the vSPC.py software, run the command below after the reboot, and query for a VM listing it doesn’t list all of the VMs that were available before the reboot. Is there way to force the software to reread the file?

python /vSPC.py --server -a 13371 -p 13370 -r 50000 --stdout --no-fork --backend File --backend-args '-f filepath’

0 Kudos
ChengHsiang
Contributor
Contributor

I have tried to use your vSPC.py without luck.

Here is what I did:

1. On vSphereClient 5.0, under the VM, I added a serial port with the following -\

     [X] Connect at power on

     Use network

           [x] Server (VM listens for connection)

          Port URI: vSPC.py

          [x] Use Virtual Serial Port Concentrator

          vSPC URI:      telnet://dispater:13370

2. On a Ubuntu machine, I installed your vSPC.py, and I did

      vSPC.py/vSPC.py 22.1.1.102     /*22.1.1.102 is the host IP*/

I got the following error:

cheng123@ubuntu:~/Documents/vSPC.py$ ./vSPC.py 22.1.1.102
Traceback (most recent call last):
  File "./vSPC.py", line 1252, in <module>
    sys.exit(do_query(args[0], admin_port))
  File "./vSPC.py", line 1041, in do_query
    s.connect((host, port))
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 111] Connection refused

Do you know what I did wrong?

Thanks in advance.

cchsiang2008@yahoo.com

0 Kudos
ZMerLynn
Contributor
Contributor

1) You need "vSPC.py -s" running somewhere, this is the terminal server. It can be the same place you connect from (I test this way).

2) The vSPC URI needs to point to where you are running "vSPC -s", i.e. in "telnet://dispater:13370", "dispater" should be the hostname or IP of the place vSPC.py is running.

0 Kudos
ChengHsiang
Contributor
Contributor

Hi ZMerLynn,

Thank you for the reply.

I have changed it according to your comment.

Now I have the following configuration:

1. On vSphereClient 5.0, under the VM, I added a serial port with the following -\

Connect at power on

Use network

Server (VM listens for connection)

Port URI: vSPC.py

Use Virtual Serial Port Concentrator

vSPC URI: telnet://22.1.1.112:13370

2. On a Ubuntu machine, I installed your vSPC.py, and I did

vSPC.py/vSPC.py -s

vSPC.py/vSPC.py 22.1.1.112 /22.1.1.102 is the host IP/

BTW, my Ubuntu “ifconfig” is the following:

cheng123@ubuntu:~/Documents/vSPC.py$ ifconfig

eth0 Link encap:Ethernet HWaddr 00:0c:29:2b:5b:99

inet addr:22.1.1.112 Bcast:22.1.1.255 Mask:255.255.255.0

inet6 addr: fe80::20c:29ff:fe2b:5b99/64 Scope:Link

UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

RX packets:2793 errors:0 dropped:0 overruns:0 frame:0

TX packets:341 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:1000

RX bytes:205674 (205.6 KB) TX bytes:20248 (20.2 KB)

Interrupt:19 Base address:0x2024

I am still getting the same error:

cheng123@ubuntu:~/Documents/vSPC.py$ ./vSPC.py 22.1.1.102

Traceback (most recent call last):

File "./vSPC.py", line 1252, in

sys.exit(do_query(args[0], admin_port))

File "./vSPC.py", line 1041, in do_query

s.connect((host, port))

File "/usr/lib/python2.7/socket.py", line 224, in meth

return getattr(self._sock,name)(*args)

socket.error: Connection timed out

Could you help? I really like to try your tool.

Cheng Hsiang

Staff Software Engineer

US R&D Center, Futurewei Technologies

Santa Clara, CA 95050

0 Kudos
ChengHsiang
Contributor
Contributor

I have changed it according to your comment.

Now I have the following configuration:

1.    On vSphereClient 5.0, under the VM, I added a serial port with the following -\

[X] Connect at power on

Use network

[x] Server (VM listens for connection)

Port URI: vSPC.py

[x] Use Virtual Serial Port Concentrator

vSPC URI: telnet://22.1.1.112:13370

2.    On a Ubuntu machine, I installed your vSPC.py, and I did

vSPC.py/vSPC.py -s

vSPC.py/vSPC.py 22.1.1.102                          /*22.1.1.102 is the host IP*/

BTW, my Ubuntu “ifconfig” is the following, and I can ping from 22.1.1.112 to 22.1.1.102.

cheng123@ubuntu:~/Documents/vSPC.py$ ifconfig

eth0      Link encap:Ethernet  HWaddr 00:0c:29:2b:5b:99

          inet addr:22.1.1.112  Bcast:22.1.1.255  Mask:255.255.255.0

          inet6 addr: fe80::20c:29ff:fe2b:5b99/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:2793 errors:0 dropped:0 overruns:0 frame:0

          TX packets:341 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000

          RX bytes:205674 (205.6 KB)  TX bytes:20248 (20.2 KB)

          Interrupt:19 Base address:0x2024

I am still getting the same error:

cheng123@ubuntu:~/Documents/vSPC.py$ ./vSPC.py 22.1.1.102

Traceback (most recent call last):

  File "./vSPC.py", line 1252, in <module>

    sys.exit(do_query(args[0], admin_port))

  File "./vSPC.py", line 1041, in do_query

    s.connect((host, port))

  File "/usr/lib/python2.7/socket.py", line 224, in meth

    return getattr(self._sock,name)(*args)

socket.error: [Errno 110] Connection timed out

0 Kudos
ChengHsiang
Contributor
Contributor

Correction:

Cheng Hsiang

Staff Software Engineer

US R&D Center, Futurewei Technologies

Santa Clara, CA 95050

0 Kudos
ChengHsiang
Contributor
Contributor

Please read the attachment. I have the screen print for the serial port configuration on vSphereClient, and the screen print for my Utunbu windows.

The Utunbu screen print has 3 windows, 1. The vSPC.py –s, 2. Ifconfig, and 3. The ping and vSPC.py 22.1.1.102 failure result.

Could you tell me what did I do wrong?

Thanks,

Cheng Hsiang

Staff Software Engineer

US R&D Center, Futurewei Technologies

Santa Clara, CA 95050

0 Kudos
ZMerLynn
Contributor
Contributor

2.    On a Ubuntu machine, I installed your vSPC.py, and I did

vSPC.py/vSPC.py -s

vSPC.py/vSPC.py 22.1.1.102                          /*22.1.1.102 is the host IP*/

I think you're missing the network picture. "vSPC.py -s" is the "vSPC.py Server". You can treat it as the center of a star network where everything connects to the center of the star:

  • ESXi connects inward to the vSPC.py Server to register serial ports.
  • To query serial ports available, you use "vSPC.py server.address", where server.address is the address of the running vSPC.py Server (in your case, it looks like this is 22.1.1.112, or if you're running it on the same machine, "localhost").
  • That query will tell you a port number (in : delimited form with some other info). This is the port number on the vSPC.py Server.

In other words, every connection should radiate towards vSPC.py Server.

I hope that helps. As a reminder, vSPC.py is an open source tool provided with no real warranty. There are a few other users using it, so you may have more luck getting your questions answered here: http://sourceforge.net/p/vspcpy/discussion/

0 Kudos
DannoDN5
Contributor
Contributor

This is great work!

I was wondering if this would allow me to virtualize a terminal-server farm using modems? We have stuck to 50+ physical servers with 8-port modem-cards each because our time-clock software ONLY talks to COM1. Luckily, we found some Equinox Avocent modems that presents 8 COM1 ports to the software and allows 8-lines per server.

Would this allow the use of multiple USB-modems per host? And multiple USB-modems concentrating into a single VM?

Thanks.

0 Kudos
utorpk
Contributor
Contributor

Hi. Thanks for vSPC.py. I tweaked it to work with inetd so that a VM's serial I/O could be saved to remote files Would there be any interest in the mods?  If so, how/where should the mods be posted? Thanks.

0 Kudos