We're going to discuss the script that would make a connection to SPICE server (CentOS 6.5 with oVirt 3.3 all-in-one plugin in my case) from recently released Fedora 20 more convenient.
Usually I get access to the virtual machine using the SPICE xpi plugin for Mozilla Firefox but for some unknown reason it had crashed every time I tried to start SPICE session from oVirt user portal (I assume that spice-xpi-2.8.90-1.fc20.x86_64 and firefox-26.0-3.fc20.x86_64 can be incompatible).
So we need a workaround here. oVirt proposes several ways to connect to the SPICE console. The first and the clearest of them didn't work in my case, thus I decided to automatize the second one that also called "manual". This operation requires the ovirt-shell and virt-viewer utilities.
First of all, make sure that you have already installed the ones:
yum install virt-viewer ovirt-engine-cli -y
Than you should prepare your ~/.ovirtshellrc file as proposed here. Here is my config (never store passwords in a such way if you care about security):
[cli] autoconnect = True autopage = True [ovirt-shell] username = admin@<your domain, "internal" by default> timeout = None extended_prompt = False url = https://<your host's fqdn>:443/api insecure = False filter = False session_timeout = None ca_file = /home/<you>/ca.crt dont_validate_cert_chain = False key_file = None cert_file = None password = <your_pass>
Don't forget to download certificate from oVirt server Certificate Authority and place it into you homedir:
wget -O ~/ca.crt http://<your host's fqdn>/ca.crt
Now let's met the ovirt-shell. Run it with a -c key and it will read the parameters from the .ovirtshellrc config:
[vitaly@asus ~]$ ovirt-shell -c ========================================== >>> connected to oVirt manager 3.3.0.0 <<< ========================================== ++++++++++++++++++++++++++++++++++++++++++ Welcome to oVirt shell ++++++++++++++++++++++++++++++++++++++++++
Start the desired VM with `action vm ${vm_name} start` , than inspect it with `show vm ${vm_name}`:
[oVirt shell (connected)]# action vm worker start status-state: complete vm-id : 827dc3fc-3631-4886-984a-decfbb3e189d [oVirt shell (connected)]# show vm worker <...> display-port : 5900 <-- you need this value <...> host-id : a7f81ab7-caa2-40de-9e40-cbe3d77c0542 <-- you need this value
Recieve one-time ticket for a SPICE session:
[oVirt shell (connected)]# action vm worker ticket status-state : complete ticket-expiry: 7200 ticket-value : QoFFUIuz+l+V <-- you need this value
Inspect the host with a command `show host ${host-id}`:
[oVirt shell (connected)]# show host a7f81ab7-caa2-40de-9e40-cbe3d77c0542 <...> certificate-subject : O=vitaly.ru,CN=rhevaio.vitaly.ru <-- you need this value
Now you can put it all together into the final command. Close ovirt-shell and return to bash:
remote-viewer --spice-ca-file ~/ca.crt --spice-host-subject "${certificate-subject}" spice://${host fqdn}/?port=display-port>\&tls-port=${display-secure_port}
Then the remote-viewer window will pop up and you'll be asked to enter the ticket value. Agree that it took so long and required a sequence of actions with the CLI. Lets make things easier with expect shell alike Python module called Pexpect. Pexpect emulates user interaction with command shell and provides well-known python tools and data structures which are so lacking during the work in any other shell but ipython.
#!/usr/bin/env python import pexpect import sys import re import os ca_crt = "~/ca.crt" #This function receives the output from ovirt-shell, purges all the #escape sequences and returns a dictionary. Please read the manuals about #string class, re module and functional programming if you're not aware of #them. def process_text(text): #Cleaning the escape sequences: answer = map(lambda x: re.sub(':?\\x1b\[.?\\.?', '', x), text) #Creating the dictionary from strings peeled from extra gaps and splitted by the #first ':' symbol return dict([map(lambda x: x.strip(), i.split(':', 1)) for i in answer]) def handle_vm(vm_name): #Starting the new process child = pexpect.spawn("ovirt-shell -c") #Wait till shell will get ready for your input child.expect("#") #Starting the vm #\r emulates Enter key press child.send("action vm {0} start\r".format(vm_name)) child.expect("#") #Getting info about the vm #f is equal to Page Down, q is the same as in `less` utility child.send("show vm {0}\rfq".format(vm_name)) child.expect("#") vm_data = process_text(child.before.split('\n')[2:-2]) #Getting info about host child.send("show host {0}\rfq".format(vm_data["host-id"])) child.expect("#") host_data = process_text(child.before.split('\n')[2:-2]) #Getting the ticket child.sendline('action vm {0} ticket'.format(vm_name)) child.expect("#") ticket_action = process_text(child.before.split('\n')[2:-2]) #I prefer the subprocess module for this purposes usually, but for a some reason #it crashes the remote-viewer. Primitive os.system() call is better cmd = ['remote-viewer', '--spice-ca-file', ca_crt, '--spice-host-subject', "'" + host_data['certificate-subject'] + "'", 'spice://{0}/?port={1}\&tls-port={2}'.format( vm_data["display-address"], vm_data['display-port'], vm_data['display-secure_port'])] #You will have to copy this value to the remote-viewer window manually print(ticket_action['ticket-value']) os.system(" ".join(cmd) + " &") if __name__ == "__main__": handle_vm(sys.argv[1])
Make your script executable and run it with a VM's name appended:
./spice_connect.py ${vm_name}
Now copy the received password from shell to the password field and enjoy the virtualization.
I would like to thank my girlfriend Anna Gorodetskaya for the picturesque wallpaper that reflects the beauty of Espoo.