Use python to write KVM scripts. Part 1: Add a GUI to use libvirt and python to manage KVM

Source: Internet
Author: User

Introduction:This series of articles, composed of two parts, explores how to use python to create scripts to use KVM to manage virtual machines. In this section, you will learn how to add a GUI to expand simple state and display tools.

This series
Use python to write scripts for KVM. Part 1: libvirtlibvirtBasic knowledge of writing kernel-based Virtual Machine (KVM) scripts with python. This section uses the concepts introduced in the previous section to build some utility applications and add a graphical user interface (GUI ). There are two main types of GUI toolkit that are both Python-bound and cross-platform. The first is QT, which is now owned by Nokia; the second is wxpython. Both have a large number of supporters, and many open-source projects are using them.

For personal preferences, I will focus on wxpython in this article. First, we will briefly introduce wxpython and the basic knowledge of correct settings. Provide some short sample programs, and thenlibvirtIntegration. This method should provide enough basic wxpython knowledge for you to build a simple program and expand the program to add features. We hope you can master these concepts and expand them to meet your specific needs.

Wxpython Basics

A good starting point is to start with some basic definitions. The wxpython library is actually based onC++WxWidgets. In the context of creating a GUIPartsIn essence, it is a building block. The top layer of the Component Hierarchy contains five independent parts:

wx.Frame,
wx.Dialog,
wx.PopupWindow,
wx.MDIParentFrameAnd
wx.MDIChildFrame.

Most examples here are based onwx.FrameBecause it essentially implements a single mode window.

In wxpython, You Can instantiate it as isFrameClass, or inherit it to add or enhance features. Be sure to understand how components are displayed in a frame so that you know how to place them correctly. The layout is determined by absolute positioning or by using the regulator.RegulatorIt is a convenient tool. When you click and drag one side or one corner to change the size of the window, it will adjust the part size.

The simplest form of the wxpython program must have some code lines for setting. A typical main routine may be similar
List 1.

Listing 1. device XML definition

if __name__ == "__main__":    app = wx.App(False)frame = MyFrame()frame.Show()app.MainLoop()

Each wxpython application iswx.App()Instance, which must be instantiated as shown in Listing 1. WhenFalsePass
wx.AppIt indicates "Do not redirect stdout and stderr to a window ". The next line is instantiated.MyFrame()Class to create a framework. Then the framework is displayed and the control is forwarded
app.MainLoop().MyFrame()Class usually contains__init__Function to use the part you selected to initialize the framework. You will also connect any part events here to their correct processing functions.

Now it is necessary to mention a convenient debugging tool with wxpython. This tool is calledPart Check Tool(See
Figure 1). You only need two lines of code. First, you must use the following code to import it:

import wx.lib.inspection

Next, you only need to callShow()Function:

wx.lib.inspectin.InspectionTool().Show()

ClickEventsThe icon displays the event dynamically when the event is activated. If you are not sure what events are supported by a specific part, this is a real quick way to view events when they occur. When an application is running, it also helps you better understand what is happening behind the scenes.

Figure 1. wxpython part Check Tool

Back to Top

Add GUI to the command line tool

This series
Use python to write scripts for KVM. Part 1: libvirt provides a simple tool to display the status of all running virtual machines (VMS. With wxpython, you can easily change this tool to a GUI tool.wx.ListCtrlA widget provides the functions required to display information in a list. To use
wx.ListCtrlPart, you must add it to your framework using the following syntax:

self.list=wx.ListCtrl(frame,id,style=wx.LC_REPORT|wx.SUNKEN_BORDER)

You can choose from a variety of different styles, includingwx.LC_REPORTAndwx.SUNKEN_BORDER. The first option sets
wx.ListCtrlSet to report mode, which is one of the four available modes. Other options include icons, icons, and lists. To addwx.SUNKEN_BORDERYou only need to use the vertical bar (|). Some styles are mutually exclusive, such as different border styles, so if you have any concerns, please refer to wxpython Wiki (see

References ).

Instantiationwx.ListCtrlAfter the widget, you can add content to it, such as the column title.InsertColumnThe method has two mandatory parameters and two optional parameters. The first is the column index, which starts from 0, followed by a string that sets the title. The third is used for formatting, which should be similar
LIST_FORMAT_CENTER,_LEFTOr_RIGHT. Finally, you can input an integer to set the fixed width or use
wx.LIST_AUTOSIZEAutomatically adjust columns.

Now you have configuredwx.ListCtrlParts, you can useInsertStringItemAnd
SetStringItem
Method to fill it with data.wx.ListCtrlEvery new line in the part must be usedInsertStringItemMethod. Two mandatory Parameters specify where to insert, including the value 0 inserted at the top of the list and the string to insert at this position.InsertStringItemReturns an integer that indicates the number of rows inserted into the string. You can call
GetItemCount(), Use the return value to append the index to the bottom, as shown in figure
List 2.

List 2. Gui version of the command line tool

import wximport libvirtconn=libvirt.open("qemu:///system")class MyApp(wx.App):    def OnInit(self):        frame = wx.Frame(None, -1, "KVM Info")        id=wx.NewId()        self.list=wx.ListCtrl(frame,id,style=wx.LC_REPORT|wx.SUNKEN_BORDER)        self.list.Show(True)        self.list.InsertColumn(0,"ID")        self.list.InsertColumn(1,"Name")        self.list.InsertColumn(2,"State")        self.list.InsertColumn(3,"Max Mem")        self.list.InsertColumn(4,"# of vCPUs")        self.list.InsertColumn(5,"CPU Time (ns)")        for i,id in enumerate(conn.listDomainsID()):            dom = conn.lookupByID(id)            infos = dom.info()            pos = self.list.InsertStringItem(i,str(id))             self.list.SetStringItem(pos,1,dom.name())            self.list.SetStringItem(pos,2,str(infos[0]))            self.list.SetStringItem(pos,3,str(infos[1]))            self.list.SetStringItem(pos,4,str(infos[3]))            self.list.SetStringItem(pos,5,str(infos[2]))                    frame.Show(True)        self.SetTopWindow(frame)        return Trueapp = MyApp(0)app.MainLoop()

Figure 2 shows the results of these jobs.

Figure 2. Gui KVM information tool

You can improve the appearance of the table. A major improvement may be the re-adjustment of columns. For this reason, you canwidth =Add parametersInsertColumnCalling or using a line of code, such:

self.ListCtrl.SetColumnWidth(column,wx.LIST_AUTOSIZE)

Another thing you can do is add a regulator so that the control can be adjusted according to the parent window. Therefore, you can usewxBoxSizer. First, create the regulator and add the part you want to adjust for the main window to it. The possible code is as follows:

self.sizer = wx.BoxSizer(wx.VERTICAL)self.sizer.Add(self.list, proportion=1,flag=wx.EXPAND | wx.ALL, border=5)self.sizer.Add(self.button, flag=wx.EXPAND | wx.ALL, border=5)self.panel.SetSizerAndFit(self.sizer)

Last pairself.panel.SetSizerAndFit()Wxpython is required to set the initial size of the pane based on the minimum size of the embedded part regulator. This helps you provide an initial screen of reasonable size based on the screen content.

Back to Top

Control flow based on user operations

Aboutwx.ListCtrlOne benefit of a widget is that you can detect when a user clicks a specific part of the widget and perform an operation based on the information. This feature allows you to sort columns in a forward or backward direction alphabetically by clicking the column title. A callback mechanism is used to complete this task. You must provide a function that binds parts with the processing method to process each operation you want to process. Therefore
BindMethod.

Each part has a certain number of associated events. There are also events associated with objects such as the mouse. The mouse event hasEVT_LEFT_DOWN,EVT_LEFT_UPAnd
EVT_LEFT_DCLICKSuch name and naming conventions are the same as those of other buttons. You canEVT_MOUSE_EVENTSType to process all mouse events. The difficulty lies in capturing events in the context of the application or window you are interested in.

When the control is passed to the event processing function, it must perform the necessary steps to process the operation, and then return the control to its previous location. This is an event-driven programming model. Every GUI must implement it to process user operations in a timely manner. Many modern GUI applications implement multithreading to avoid making the user feel that the program has no response. This topic will be briefly introduced later.

A timer represents another type of event that a program may have to handle. For example, you may want to perform regular monitoring at user-defined intervals. You will need to provide a screen where you can specify the interval and then start a timer to trigger an event when it expires. An event is triggered when the timer expires. You can use this event to activate a piece of code. You may need to set or re-start timing based on your preferences. You can easily use this technology to develop VM monitoring tools.

Listing 3 provides a simple demo application that contains buttons and static text lines. Use
wx.StaticTextIs an easy way to output strings to a window. The idea is to click this button once to start a timer, record the start time, and change the label
Stop. Click the button again to enter the end time text box and change the button back.Start.

Listing 3. Simple Applications that contain buttons and static text

import wxfrom time import gmtime, strftimeclass MyForm(wx.Frame):     def __init__(self):        wx.Frame.__init__(self, None, wx.ID_ANY, "Buttons")        self.panel = wx.Panel(self, wx.ID_ANY)         self.button = wx.Button(self.panel, id=wx.ID_ANY, label="Start")        self.button.Bind(wx.EVT_BUTTON, self.onButton)    def onButton(self, event):        if self.button.GetLabel() == "Start":            self.button.SetLabel("Stop")            strtime = strftime("%Y-%m-%d %H:%M:%S", gmtime())            wx.StaticText(self, -1, 'Start Time = ' + strtime, (25, 75))        else:            self.button.SetLabel("Start")            stptime = strftime("%Y-%m-%d %H:%M:%S", gmtime())            wx.StaticText(self, -1, 'Stop Time = ' + stptime, (25, 100)) if __name__ == "__main__":    app = wx.App(False)    frame = MyForm()    frame.Show()    app.MainLoop()

Back to Top

Enhanced monitoring Gui

Now you can add the simple monitoring GUI described above. Before you have everything you need to create an application, you need to understand another aspect of wxpython. Directionwx.ListCtrlAdd a check box on the first line of the widget to perform operations on multiple lines based on the check box status. Therefore, you can use
Mixin. In essence,MixinIs a helper class that adds a certain type of functionality to the parent component. To add a check box Mixin, you only need to use the following code to instantiate it:

listmix.CheckListCtrlMixin.__init__(self)

You can also use the event to add and click the column title to select or clear all check boxes. In this way, you can start or stop all VMS with just a few clicks. You need to write some event handler functions to respond to the appropriate events in the same way as changing the button tag. The following is the code line required to set the column to click the event processing function:

self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick, self.list)

wx.EVT_LIST_COL_CLICKTriggered when you click any column title. You can useevent.GetColumn()Method. Below is
OnColClickA simple event processing function:

def OnColClick(self, event):    print "column clicked %d\n" % event.GetColumn()event.Skip()

If you want to spread events to other processing functions,event.Skip()Call is very important. Although it may not be needed in this instance, when multiple processing functions need to process the same event, it may cause problems if they are not used. The wxpython wiki site has a good discussion of event propagation, which is much more detailed than what I have described here.

Finally, add code to the two buttons to start or stop all selected VMS. Just a few lines of code can be iteratedwx.ListCtrlAnd obtain the vm id, as shown in figure

List 4.

Listing 4. Start and Stop the selected VM

#!/usr/bin/env pythonimport wximport wx.lib.mixins.listctrl as listmiximport libvirtconn=libvirt.open("qemu:///system")class CheckListCtrl(wx.ListCtrl, listmix.CheckListCtrlMixin,                                  listmix.ListCtrlAutoWidthMixin):    def __init__(self, *args, **kwargs):        wx.ListCtrl.__init__(self, *args, **kwargs)        listmix.CheckListCtrlMixin.__init__(self)        listmix.ListCtrlAutoWidthMixin.__init__(self)        self.setResizeColumn(2)class MainWindow(wx.Frame):    def __init__(self, *args, **kwargs):        wx.Frame.__init__(self, *args, **kwargs)        self.panel = wx.Panel(self)        self.list = CheckListCtrl(self.panel, style=wx.LC_REPORT)        self.list.InsertColumn(0, "Check", width = 175)        self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick, self.list)        self.list.InsertColumn(1,"Max Mem", width = 100)        self.list.InsertColumn(2,"# of vCPUs", width = 100)        for i,id in enumerate(conn.listDefinedDomains()):            dom = conn.lookupByName(id)            infos = dom.info()            pos = self.list.InsertStringItem(1,dom.name())             self.list.SetStringItem(pos,1,str(infos[1]))            self.list.SetStringItem(pos,2,str(infos[3]))        self.StrButton = wx.Button(self.panel, label="Start")        self.Bind(wx.EVT_BUTTON, self.onStrButton, self.StrButton)        self.sizer = wx.BoxSizer(wx.VERTICAL)        self.sizer.Add(self.list, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)        self.sizer.Add(self.StrButton, flag=wx.EXPAND | wx.ALL, border=5)        self.panel.SetSizerAndFit(self.sizer)        self.Show()    def onStrButton(self, event):        if self.StrButton.GetLabel() == "Start":    num = self.list.GetItemCount()            for i in range(num):                if self.list.IsChecked(i):                    dom = conn.lookupByName(self.list.GetItem(i, 0).Text)                    dom.create()                    print "%d started" % dom.ID()     def OnColClick(self, event):         item = self.list.GetColumn(0)         if item is not None:             if item.GetText() == "Check":                 item.SetText("Uncheck")                 self.list.SetColumn(0, item)                 num = self.list.GetItemCount()                 for i in range(num):                     self.list.CheckItem(i,True)             else:                 item.SetText("Check")                 self.list.SetColumn(0, item)                 num = self.list.GetItemCount()                 for i in range(num):                     self.list.CheckItem(i,False)         event.Skip() app = wx.App(False)win = MainWindow(None)app.MainLoop()

In terms of VM status in KVM, there are two highlights: when usinglibvirtInlistDomainsID()Method, the running VM is displayed. To view machines that are not running, you must use
listDefinedDomains(). To know which VMS can be started and which ones can be stopped, you must keep the two parts independent.

Back to Top

Conclusion

This document describes how to use wxpython to build a GUI package.libvirtTo manage KVM. The wxpython library has rich functions and provides many components to support building Gui-based applications with professional appearances. This article only introduces a small part of the features, and we hope you can further explore them. Please refer to more

References to help your applications run properly.

References

Learning

  • libvirtWebsite: view the entire website for more information.

  • Reference manuallibvirt: Complete access
    libvirtAPI reference manual.

  • Python.org: Find your desired Python resources from the official website.
  • Wxpython.org: get more information about wxpython.
  • Wxpython wiki: You can use many tutorials to expand your knowledge.
  • Developerworks podcasts: Listen to interesting interviews and discussions for software developers.
  • Developerworks demonstration center: Watch free demos and learn about IBM and open-source technologies and product features.
  • Stay tuned to developerworks
    Technical activities and network broadcasts.

  • Visit developerworks
    The Open Source Area provides rich how-to information, tools, and project updates, as well as the most popular articles and tutorials to help you develop with open source code technology, they are used in combination with IBM products.

    Http://www.ibm.com/developerworks/cn/opensource/os-python-kvm-scripting2/

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.