431602b983b1a8b02845dbdb3df789c39ebe353b
[mclu.git] / mclu_build.py
1 #!/usr/bin/python
2 # mclu (mini cluster)
3 # Copyright (C) 2014 Red Hat Inc.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
19 import argparse
20 import os
21 import re
22 import subprocess
23 import sys
24 import libvirt
25
26 import config
27 import lib
28 import libvirt_xml
29
30 def cmdline (subparsers):
31     p = subparsers.add_parser (
32         'build',
33         help='build and run a new virtual machine',
34     )
35     p.add_argument (
36         '--memory', default=1024, type=int,
37         help='RAM to give to guest (default unit is megabytes)'
38     )
39     p.add_argument (
40         '--vcpus', default=4, type=int,
41         help='virtual CPUs to give to guest'
42     )
43     p.add_argument (
44         '--virtio', default=True,
45         help='use virtio disks and network'
46     )
47     p.add_argument (
48         '--size', required=True,
49         help='size of disk'
50     )
51     p.add_argument (
52         'name',
53         help='name of the new VM (or use "vm:name")'
54     )
55     p.add_argument (
56         'os_version',
57         help='OS & version of guest (see virt-builder docs)'
58     )
59     p.add_argument (
60         'vbargs', nargs='*',
61         help='virt-builder arguments (after "--")'
62     )
63     p.set_defaults (run=run)
64
65 def run (c, args, nodes):
66     # Did the user request a particular node?  If not, we'll run it
67     # on any node which is up.
68     m = re.match (r'^(.*):(.*)$', args.name)
69     if m:
70         node_name = m.group (1)
71         vm_name = m.group (2)
72         if node_name in nodes:
73             node = nodes[node_name]
74             if not node.ping ():
75                 sys.exit ("error: requested node (%s) is not up, use mclu on %s" %
76                           (node_name, node_name))
77         else:
78             sys.exit ("error: requested node (%s) does not exist" % node_name)
79     else:
80         node = lib.pick_any_node_which_is_up (nodes)
81         vm_name = args.name
82
83     # Get all the guests, so we can tell if the name is a duplicate.
84     running, inactive = lib.get_all_guests (c, nodes.values ())
85
86     if vm_name in running or vm_name in inactive:
87         sys.exit ("error: node name (%s) already exists" % vm_name)
88
89     output = '%s/%s.img' % (c['images_dir'], vm_name)
90
91     # Call out to virt-builder to build the disk image.
92     vbargs = [
93         config.VIRT_BUILDER,
94         args.os_version,
95         '--output', output,
96         '--format', 'qcow2',
97     ]
98     if args.size:
99         vbargs.extend (['--size', args.size])
100     if args.vbargs:
101         vbargs.extend (args.vbargs)
102     subprocess.check_call (vbargs)
103
104     # XXX Unfortunately this is necessary so qemu can access the disk.
105     os.chmod (output, 0666)
106
107     # Generate the XML.  Would be nice to use virt-install here, but
108     # it doesn't work: RHBZ#1095789
109     xml = libvirt_xml.generate_libvirt_xml (vm_name,
110                                             args.memory,
111                                             args.vcpus,
112                                             args.virtio,
113                                             output)
114
115     # Write the XML to the xmls_dir.
116     fp = open ("%s/%s.xml" % (c['xmls_dir'], vm_name), "w")
117     fp.write (xml)
118     fp.close ()
119
120     # Start the guest.
121     lib.start_guest (c, node, vm_name)
122     print "guest built and started on node %s" % node.name