Python script to manage virtual machines with python API for libvirt.

Most of times I use virt-manager to manage VMs but sometimes, I have to manage VMs on other hosts over ssh when connected over VPN or while I am working remotely. GUI like virt-manager thus becomes slow, and hence I like to use cli commands and nothing is better than virsh. But here is simple script that I use sometimes to manage the VMs with CLI based menu. Hope you find it useful.

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2016 Amit Agarwal <http://blog.amit-agarwal.co.in>
# Python scripts to manage virtual machines.
# 
# Distributed under terms of the MIT license.

"""
python wrapper for libvirt
"""

import libvirt
import sys
import pprint
from xml.dom import minidom

import os

hv_host="localhost"
names = []



def chhost():
    global hv_host
    global uri
    global conn

    print "Host is now set to "+hv_host

    try:
        ui = raw_input ("Provide the uri in format user@host : ")
    except:
        ui=''

    if len(ui) > 2 :
        if uri.find("lxc") :
            print "Using LXC uri"
        else:
            uri = "qemu+ssh://"+ui+"/system"
    else:
        uri = "qemu:///system"

    print uri + " is set as URI"
    conn = libvirt.open(uri)
    if conn == None:
        print 'Failed to open connection to the hypervisor'
        sys.exit(1)
    else:
        print "Connection established with "+uri

def vms(state):

    global names
    global conn
    if state == 'running' :
        active_hosts = conn.listDomainsID()
        if (len (active_hosts) == 0 ) :
            print "No Running VMs"
            return
        for i in range ( len (active_hosts) ):
            dom0 = conn.lookupByID(active_hosts[i])
            print "\t%d\t%s"%(active_hosts[i], dom0.name())
        val = input ( "Enter the ID ")
        return int(val)
    else :
        names = conn.listDefinedDomains()
        for i in range ( len (names) ):
            print "\t%d\t%s" %(i, names[i])
        tostart = input("Please enter number to start the VM :: ")
        print "Starting VM "+names[tostart]
        return names[tostart]

def writer(stream, data, buffer):
    buffer.write(data)

def start():
    global names
    global conn
    tostart = vms('')
    dom0 = conn.lookupByName(tostart)
    dom0.create()

def stop():
    print "List currently running VMs"
    val = vms('running')
    dom0 = conn.lookupByID(val)
    dom0.shutdown()


def view():
    print "List currently running VMs"
    val = vms('running')
    dom0 = conn.lookupByID(val)
    os.system("virt-viewer " + dom0.name() + " &" );

def viewip():
    val = vms('running')
    print "ID Returned is "+str(val)
    dom0 = conn.lookupByID(val)
    pprint.pprint (dom0.info())
    # pprint.pprint (dom0.GetInterfacesAddresses())

    for lease in conn.networkLookupByName("default").DHCPLeases():
        print(lease)

    raw_xml = dom0.XMLDesc (0)
    xml = minidom.parseString (raw_xml)
    interfaceTypes = xml.getElementsByTagName ( 'interface')
    for interfaceType in interfaceTypes :
        print ( 'interface: type=' +interfaceType.getAttribute ( 'type'))
        interfaceNodes = interfaceType.childNodes
        for interfaceNode in interfaceNodes :
            if interfaceNode.nodeName [0:1] != '#' :
                print ( '  ' +interfaceNode.nodeName)
                for attr in interfaceNode.attributes.keys ():
                    print ( '    ' +interfaceNode .attributes[attr].name + ' = ' + interfaceNode.attributes[attr].value)

    print 'View'


def state_to_string (state):
    statearr = [ "", "Running" ]
    return statearr[state[0]]

def info(dom):
    states = {
        libvirt.VIR_DOMAIN_NOSTATE: 'no state',
        libvirt.VIR_DOMAIN_RUNNING: 'running',
        libvirt.VIR_DOMAIN_BLOCKED: 'blocked on resource',
        libvirt.VIR_DOMAIN_PAUSED: 'paused by user',
        libvirt.VIR_DOMAIN_SHUTDOWN: 'being shut down',
        libvirt.VIR_DOMAIN_SHUTOFF: 'shut off',
        libvirt.VIR_DOMAIN_CRASHED: 'crashed',
    }

    [state, maxmem, mem, ncpu, cputime] = dom.info()
    return '%s' % (states.get(state, state))

def viewdets():
    global conn
    global names
    columns = 3


    domains = map(conn.lookupByName, names)

    ids = conn.listDomainsID()
    running = map(conn.lookupByID, ids)



    print 'Defined domains:'
    for row in map(None, *[iter(domains)] * columns):
        for domain in row:
            if domain:
                print "%s, %s" %( dom.name(), info(domain)),
        print
    print

    print 'Running domains:'
    for row in map(None, *[iter(running)] * columns):
        for domain in row:
            if domain:
                print info(domain),
        print



    print "Id    Name                           State"
    print "-" * 52
    for dom in conn.listAllDomains() :
        [state, maxmem, mem, ncpu, cputime] = dom.info()
        print "%3s %-31s%s" %\
            (dom.ID() if dom.ID() > 0 else "-",
             dom.name(),
             info(dom))
        # if dom.ID() > 0:
        # cpu_stats = dom.getCPUStats(False)
        # for (i, cpu) in enumerate(cpu_stats):
        # print 'CPU #%d Time: %.2lf sec' % (i, cpu['cpu_time'] / 1000000000.0 )

    print "View all details"
    print names
    active_hosts = conn.listDomainsID()
    if  len ( active_hosts ) > 0 :
        for id in active_hosts:
            dom = conn.lookupByID(id)
            infos = dom.info()
            print 'ID = %d' % id
            print 'Name =  %s' % dom.name()
            print 'State = %d' % infos[0]
            print 'Max Memory = %d' % infos[1]
            print 'Number of virt CPUs = %d' % infos[3]
            print 'CPU Time (in ns) = %d' % infos[2]
            print ' '

def quit():
    print "Exit on user request"
    sys.exit(0)


def menu():
    mm = [ {
        'Description': 'Change the host',
        'function' : chhost,
    },
          {
              'Description' : 'Start a Container' ,
              'function' : start
          },
          {
              'Description' : 'View a container',
              'function' : view
          },
          {
              'Description' : 'Stop a container',
              'function' : stop
          },
          {
              'Description' : "Take Screenshot",
              'function' : screenshot,
          },
          {
              'Description' :'View IP of Container',
              'function' : viewip,
          },
          {
              'Description' : 'View all Details of Conatainer',
              'function' : viewdets,
          },
          {
              'Description' : 'Quit',
              'function' : quit,
          },

          ]
    print "Virsh wrapper by Amit Agarwal"
    i = 0
    for i in range ( len (mm) ):
        print "\t%d) %s" % (i, mm[i]['Description'] )

    try:
        val = int(raw_input ("Please Select ::"))
    except:
        val=-1

    print len(mm)
    if val >= 0 and val < len (mm) :
        mm[val]['function']()


uri = "qemu:///system"
conn = libvirt.open(uri)
if conn == None:
    print 'Failed to open connection to the hypervisor'
    sys.exit(1)

while 1:
    menu()

web services in c with cgi

I was trying to setup a simply webservice to reply to POST requests. Earlier this was being done in tomcat which seem a little overkill to me since I already had a webserver up and running. So, a quick c program to respond to request is all that I needed. And here is the result.

/*
 * =====================================================================================
 *
 *       Filename:  Login.cpp
 *
 *    Description:
 *
 *        Version:  1.0

 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Amit Agarwal (),
 *   Organization:
*
* == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == =
    */
#include 
#include 
#include 


#define MAXLEN 1024

#ifdef DBG
#define DEBUG(a,b) fprintf(stderr, a, b);
#else
#define DEBUG(a,b) 
#endif

#define HEAD "n"
#define TAIL ""

int main(void)
{

    char input[MAXLEN];
    char * data;
    char*lenstr;
    long len;


    printf("%s%c%cnn",
           "Content-Type:text/xml;charset=iso-8859-1", 13, 10);

    // len = getenv("QUERY_STRING"); // This is for GET
    lenstr = getenv("CONTENT_LENGTH");
    DEBUG( "Length string is %sn", lenstr);

    if(lenstr == NULL || sscanf(lenstr,"%ld",&len)!=1 || len > MAXLEN)
        printf("Error in invocation - wrong FORM probably.");
DEBUG( "Length is %ldn", len);
{
int count=0;
while ( count < len )
input[count++] = getchar();
input[count]='?';
DEBUG ( "Read characters = %dn", count)
}

//fprintf(stderr, "VAlue is %sn", input);
///unencode(input + 5 , input + len, data);

data = input;
DEBUG("Data value is %sn", data);

printf(HEAD);
printf("Everything else goes heren");
printf(TAIL);

fprintf(stderr, "Sent resp: tid[%s], eaid[%s], tcode[%s]n", tid, eaid, tcode);
}

Additionally, the makefile:

all:
gcc -o Login Login.c -Wall

debug:
gcc -o Login Login.c -Wall -DDBG=1

And finally, compile this with make command and put in the cgi-bin folder and that is all that you need 🙂

git – plot the history

git has a very simple solution to see all the commits in a graphical form. If you need to understand all the commits history all you need is

git graphviz|dot -Tpng  -o /tmp/a.png

This will generate a file called /tmp/a.png which will diplay the complete commit history.