Add vm listing

This commit is contained in:
Piotr Dobrowolski 2017-03-30 12:21:41 +02:00
parent 3fc7c633d4
commit e00189e21f
2 changed files with 172 additions and 3 deletions

View File

@ -3,3 +3,5 @@ Jinja2>=2.8
netaddr>=0.7.18
libvirt-python>=1.3.1
ovh==0.4.7
termcolor==1.1.0
terminaltables==3.1.0

173
vm.py
View File

@ -1,11 +1,14 @@
#!/usr/bin/env python
"""vm - simple libvirt wrapper
usage: vm [--version] [--help] <command> [<args>...]
usage: vm [--version] [--help] [options] <command> [<args>...]
Available commands are:
create Create new VM from cloud image
ip:list List available OVH IPs
ip:sync Create missing vMACs for OVH IPs
Available options are:
-l, --libvirt=URI Use provided URI to connect to libvirt host
"""
from __future__ import print_function
@ -29,6 +32,7 @@ import libvirt
import ovhtool
import ovh
import ovh.exceptions
from collections import namedtuple
BASE = os.path.dirname(os.path.abspath(__file__))
@ -73,7 +77,8 @@ class Instance(object):
ovh_ips = None
def __init__(self, name, cpus, memory, storage, template,
ip=None, mac=None, dns=None, password=None):
ip=None, mac=None, dns=None, password=None,
libvirt_conn=None):
# General
self.name = name
self.cpus = cpus
@ -98,6 +103,8 @@ class Instance(object):
if not self.password:
self.password = gen_password()
self._libvirt_conn = libvirt_conn
def create(self):
self.prepare_datasource()
self.prepare_storage()
@ -133,10 +140,16 @@ class Instance(object):
self.template_path, self.storage_path)
def prepare_instance(self):
conn = libvirt.open(None)
conn = self.libvirt_conn
dom = conn.defineXML(self.libvirt_definition)
dom.create()
@property
def libvirt_conn(self):
if not self._libvirt_conn:
self._libvirt_conn = libvirt.open(None)
return self._libvirt_conn
def generate_ip(self):
'''Generates IP address when none was provided by user'''
if not self.ovh_ips:
@ -271,16 +284,170 @@ ey?
return 0
from xml.dom import minidom
DomainInfo = namedtuple('DomainInfo', [
'state', 'max_memory', 'memory', 'vcpus', 'cpu_time'
])
BlockInfo = namedtuple('BlockInfo', [
'capacity', 'allocation', 'physical'
])
class LibvirtInterface(object):
def __init__(self, elm):
self.elm = elm
@property
def type(self):
return self.elm.getAttribute('type')
@property
def mac(self):
return self.elm.getElementsByTagName('mac')[0].getAttribute('address')
@property
def alias(self):
return self.elm.getElementsByTagName('alias')[0].getAttribute('name')
@property
def source(self):
return self.elm.getElementsByTagName('source')[0].getAttribute('bridge')
class LibvirtDisk(object):
def __init__(self, elm, dom):
self.elm = elm
self.domain = dom
@property
def type(self):
return self.elm.getAttribute('type')
@property
def source(self):
src = self.elm.getElementsByTagName('source')
if src:
return src[0].getAttribute('dev')
@property
def info(self):
if self.source:
return BlockInfo(*self.domain.blockInfo(self.source))
@property
def present(self):
return bool(self.source)
class LibvirtDomain(object):
_xml = None
def __init__(self, dom, conn=None):
self.domain = dom
self.conn = conn
@property
def xml(self):
if not self._xml:
self._xml = minidom.parseString(self.domain.XMLDesc(0))
return self._xml
@property
def info(self):
return DomainInfo(*self.domain.info())
@property
def name(self):
return self.domain.name()
@property
def interfaces(self):
for interface in self.xml.getElementsByTagName('interface'):
yield LibvirtInterface(interface)
@property
def disks(self):
for disk in self.xml.getElementsByTagName('disk'):
yield LibvirtDisk(disk, self.domain)
def cmd_list(args):
'''usage: vm list
List existing virtual machines with a summary
'''
import terminaltables
from termcolor import colored
global libvirt_conn
def domains_list():
state_colors = {
1: 'green',
3: 'yellow',
5: 'red',
}
yield ['Name', 'RAM', 'vCPUs', 'IP', 'Storage']
mem_sum = 0
for dom in libvirt_conn.listAllDomains():
state, max_mem, mem, vcpus, cputime = dom.info()
d = LibvirtDomain(dom)
formatted_mem = '%dM' % (mem/1024)
if mem != max_mem:
formatted_mem += colored(' (%dM)' % (max_mem/1024), 'grey')
mem_sum += mem
disk_info = []
for disk in d.disks:
if disk.type == 'block' and disk.present:
disk_info.append(
('%dG ' + colored('(%s)', 'grey')) % (
disk.info.physical/(1024*1024*1024), disk.source
)
)
yield [
colored(d.name, state_colors.get(state, None)),
formatted_mem,
vcpus,
'',
', '.join(disk_info)
]
yield []
yield ['', '%dM' % (mem_sum/1024), '', '', '']
table = terminaltables.SingleTable(list(domains_list()))
table.justify_columns={
0: 'right', 1: 'right', 2: 'right'
}
print(table.table)
commands = {
'create': cmd_create,
'list': cmd_list,
'ip:list': cmd_iplist,
'ip:sync': cmd_ipsync,
'help': cmd_help,
}
libvirt_conn = None
def main(gargv):
global libvirt_conn
args = docopt(__doc__, version='vm '+__version__,
options_first=True, argv=gargv)
libvirt_conn = libvirt.open(args['--libvirt'])
cmd = args['<command>'].lower()
argv = [cmd] + args['<args>']
if cmd not in commands: