diff options
| author | Amy Fong <amy.fong@windriver.com> | 2014-05-21 14:35:15 -0400 |
|---|---|---|
| committer | Bruce Ashfield <bruce.ashfield@windriver.com> | 2014-05-23 23:42:55 -0400 |
| commit | fb1d6f23fa01c0217ed3f6778d8033dd0030db2a (patch) | |
| tree | 36dc89d6b66050a56cbca2f2f7c90229ebcb8854 /meta-openstack/Documentation/testsystem/launch.py | |
| parent | 6350b155270f7f086624db36ecc6e6008ebcd378 (diff) | |
| download | meta-cloud-services-fb1d6f23fa01c0217ed3f6778d8033dd0030db2a.tar.gz | |
Testing documentation
Add documentation for testing swift, ceph, heat.
Create a script and instructions on a script that launches a controller
and a specified number of compute nodes.
Signed-off-by: Amy Fong <amy.fong@windriver.com>
Diffstat (limited to 'meta-openstack/Documentation/testsystem/launch.py')
| -rwxr-xr-x | meta-openstack/Documentation/testsystem/launch.py | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/meta-openstack/Documentation/testsystem/launch.py b/meta-openstack/Documentation/testsystem/launch.py new file mode 100755 index 0000000..e177773 --- /dev/null +++ b/meta-openstack/Documentation/testsystem/launch.py | |||
| @@ -0,0 +1,304 @@ | |||
| 1 | #!/usr/bin/env python | ||
| 2 | |||
| 3 | import sys | ||
| 4 | import grp | ||
| 5 | import pwd | ||
| 6 | import os | ||
| 7 | import libvirt | ||
| 8 | import ConfigParser | ||
| 9 | import subprocess | ||
| 10 | import shutil | ||
| 11 | import distutils.spawn | ||
| 12 | import platform | ||
| 13 | |||
| 14 | # this does a very basic test to see if the required packages | ||
| 15 | # are installed, extend list as required | ||
| 16 | def checkPackages(): | ||
| 17 | sys_ok = True | ||
| 18 | check_apps = [ "virsh", "qemu-system-x86_64", "libvirtd" ] | ||
| 19 | for app in check_apps: | ||
| 20 | if distutils.spawn.find_executable(app) == None: | ||
| 21 | print( "Missing: " + app) | ||
| 22 | sys_ok = False | ||
| 23 | if not sys_ok: | ||
| 24 | print("The required libvirt/qemu packages are missing...") | ||
| 25 | distro = platform.dist()[0] | ||
| 26 | if distro == "debian" or distro == "Ubuntu": | ||
| 27 | print( "This appears to be a Debian/Ubuntu distribution\nPlease install " + | ||
| 28 | "packages like libvirt-bin, qemu-system-x86,..." ) | ||
| 29 | elif distro == "redhat" or distro == "fedora": | ||
| 30 | print( "This appears to be a Redhat/Fedora distribution\nPlease install " + | ||
| 31 | "packages like libvirt-client, libvirt-daemon, qemu-system-x86, ..." ) | ||
| 32 | exit(1) | ||
| 33 | return | ||
| 34 | |||
| 35 | def networkInterfaces(): | ||
| 36 | ifaces = [] | ||
| 37 | for line in open('/proc/net/dev', 'r'): | ||
| 38 | if_info = line.split(":", 1) | ||
| 39 | if len(if_info) > 1: | ||
| 40 | ifaces.append( if_info[0].strip() ) | ||
| 41 | return ifaces | ||
| 42 | |||
| 43 | def destroyNetwork(conn, network_name): | ||
| 44 | networks = conn.listNetworks() + conn.listDefinedNetworks() | ||
| 45 | if network_name in networks: | ||
| 46 | try: | ||
| 47 | nw = conn.networkLookupByName(network_name) | ||
| 48 | if nw.isActive(): | ||
| 49 | nw.destroy() | ||
| 50 | nw.undefine() | ||
| 51 | except: | ||
| 52 | print( "Failed to destroy network: %s" % network_name ) | ||
| 53 | exit( 1 ) | ||
| 54 | |||
| 55 | def restartDomain(conn, domain_name): | ||
| 56 | try: | ||
| 57 | domain = conn.lookupByName(domain_name) | ||
| 58 | except: | ||
| 59 | print( "restartDomain: Warning domain " + domain_name + " doesn't exist." ) | ||
| 60 | return | ||
| 61 | if domain.isActive(): | ||
| 62 | domain.reboot() | ||
| 63 | |||
| 64 | def destroyDomain(conn, auto_destroy, domain_name): | ||
| 65 | try: | ||
| 66 | domain = conn.lookupByName(domain_name) | ||
| 67 | except: | ||
| 68 | return | ||
| 69 | if domain.isActive(): | ||
| 70 | if auto_destroy: | ||
| 71 | print( "Auto destroy enabled, destroying old instance of domain %s" % domain_name ) | ||
| 72 | domain.destroy() | ||
| 73 | else: | ||
| 74 | print( "Domain %s is active, abort..." % domain_name ) | ||
| 75 | print( "To stop: virsh -c %s destroy %s " % ( uri , domain_name ) ) | ||
| 76 | exit(0) | ||
| 77 | domain.undefine() | ||
| 78 | |||
| 79 | def startDomain(conn, auto_destroy, domain_name, xml_desc): | ||
| 80 | print( "Starting %s...\n%s" % ( domain_name, xml_desc ) ) | ||
| 81 | destroyDomain(conn, auto_destroy, domain_name) | ||
| 82 | try: | ||
| 83 | conn.defineXML(xml_desc) | ||
| 84 | domain = conn.lookupByName(domain_name) | ||
| 85 | domain.create() | ||
| 86 | print( "Starting domain %s..." % domain_name ) | ||
| 87 | print( "To connect to the console: virsh -c %s console %s" % ( uri, domain_name ) ) | ||
| 88 | print( "To stop: virsh -c %s destroy %s" % ( uri, domain_name ) ) | ||
| 89 | except Exception as e: | ||
| 90 | print( e ) | ||
| 91 | exit(1) | ||
| 92 | |||
| 93 | def make_nw_spec(network_name, bridge_nw_interface, network, auto_assign_ip): | ||
| 94 | spec = '<network>' | ||
| 95 | spec += '<name>' + network_name + '</name>' | ||
| 96 | spec += '<bridge name="' + bridge_nw_interface + '"/>' | ||
| 97 | spec += '<forward/>' | ||
| 98 | spec += '<ip address="' + network + '" netmask="255.255.255.0">' | ||
| 99 | if auto_assign_ip: | ||
| 100 | nw_parts = network.split('.') | ||
| 101 | nw_parts[-1] = "2" | ||
| 102 | start_dhcp = '.'.join(nw_parts) | ||
| 103 | nw_parts[-1] = "254" | ||
| 104 | end_dhcp = '.'.join(nw_parts) | ||
| 105 | spec += '<dhcp>' | ||
| 106 | spec += '<range start="' + start_dhcp + '" end="' + end_dhcp + '"/>' | ||
| 107 | spec += '</dhcp>' | ||
| 108 | spec += '</ip>' | ||
| 109 | spec += '</network>' | ||
| 110 | return spec | ||
| 111 | |||
| 112 | def make_spec(name, network, kernel, disk, bridge_nw_interface, emulator, auto_assign_ip, ip): | ||
| 113 | if not os.path.exists(kernel): | ||
| 114 | print( "Kernel image %s does not exist!" % kernel ) | ||
| 115 | exit(1) | ||
| 116 | if not os.path.exists(disk): | ||
| 117 | print( "Disk %s does not exist!" % disk ) | ||
| 118 | exit(1) | ||
| 119 | if auto_assign_ip: | ||
| 120 | ip_spec = 'dhcp' | ||
| 121 | else: | ||
| 122 | ip_spec = ip + '::' + network + ':255.255.255.0:' + name + ':eth0:off' | ||
| 123 | spec = '<domain type=\'kvm\'>' | ||
| 124 | spec += ' <name>' + name + '</name>' | ||
| 125 | spec += ' <memory>4096000</memory>' | ||
| 126 | spec += ' <currentMemory>4096000</currentMemory>' | ||
| 127 | spec += ' <vcpu cpuset=\'1\'>1</vcpu>' | ||
| 128 | spec += ' <cpu>' | ||
| 129 | spec += ' <model>kvm64</model>' | ||
| 130 | spec += ' </cpu>' | ||
| 131 | spec += ' <os>' | ||
| 132 | spec += ' <type arch=\'x86_64\' machine=\'pc\'>hvm</type>' | ||
| 133 | spec += ' <kernel>' + kernel + '</kernel>' | ||
| 134 | spec += ' <boot dev=\'hd\'/>' | ||
| 135 | spec += ' <cmdline>root=/dev/vda rw console=ttyS0 ip=' + ip_spec + '</cmdline>' | ||
| 136 | spec += ' </os>' | ||
| 137 | spec += ' <features>' | ||
| 138 | spec += ' <acpi/>' | ||
| 139 | spec += ' <apic/>' | ||
| 140 | spec += ' <pae/>' | ||
| 141 | spec += ' </features>' | ||
| 142 | spec += ' <clock offset=\'utc\'/>' | ||
| 143 | spec += ' <on_poweroff>destroy</on_poweroff>' | ||
| 144 | # spec += ' <on_reboot>destroy</on_reboot>' | ||
| 145 | spec += ' <on_crash>destroy</on_crash>' | ||
| 146 | spec += ' <devices>' | ||
| 147 | spec += ' <emulator>' + emulator + '</emulator>' | ||
| 148 | spec += ' <disk type=\'file\' device=\'disk\'>' | ||
| 149 | spec += ' <source file=\'' + disk + '\'/>' | ||
| 150 | spec += ' <target dev=\'vda\' bus=\'virtio\'/>' | ||
| 151 | spec += ' </disk>' | ||
| 152 | spec += ' <interface type=\'bridge\'>' | ||
| 153 | spec += ' <source bridge=\'' + bridge_nw_interface + '\'/>' | ||
| 154 | spec += ' <model type=\'virtio\' />' | ||
| 155 | spec += ' </interface>' | ||
| 156 | spec += ' <serial type=\'pty\'>' | ||
| 157 | spec += ' <target port=\'0\'/>' | ||
| 158 | spec += ' <alias name=\'serial0\'/>' | ||
| 159 | spec += ' </serial>' | ||
| 160 | spec += ' <console type=\'pty\'>' | ||
| 161 | spec += ' <target type=\'serial\' port=\'0\'/>' | ||
| 162 | spec += ' <alias name=\'serial0\'/>' | ||
| 163 | spec += ' </console>' | ||
| 164 | spec += ' </devices>' | ||
| 165 | spec += '</domain>' | ||
| 166 | return spec | ||
| 167 | |||
| 168 | def getConfig(config, section, key): | ||
| 169 | try: | ||
| 170 | return os.path.expandvars(config.get(section, key)) | ||
| 171 | except: | ||
| 172 | print( "Configuration file error! Missing item (section: %s, key: %s)" % ( section, key ) ) | ||
| 173 | exit(1) | ||
| 174 | |||
| 175 | # does the user have access to libvirt? | ||
| 176 | eligible_groups = [ "libvirt", "libvirtd" ] | ||
| 177 | eligible_user = False | ||
| 178 | euid = os.geteuid() | ||
| 179 | if euid == 0: | ||
| 180 | eligible_user = True | ||
| 181 | else: | ||
| 182 | username = pwd.getpwuid(euid)[0] | ||
| 183 | groups = [g.gr_name for g in grp.getgrall() if username in g.gr_mem] | ||
| 184 | for v in eligible_groups: | ||
| 185 | if v in groups: | ||
| 186 | eligible_user = True | ||
| 187 | |||
| 188 | checkPackages() | ||
| 189 | |||
| 190 | if not eligible_user: | ||
| 191 | sys.stderr.write("You need to be the 'root' user or in group [" + '|'.join(eligible_groups) + "] to run this script.\n") | ||
| 192 | exit(1) | ||
| 193 | |||
| 194 | if len(sys.argv) != 3: | ||
| 195 | sys.stderr.write("Usage: "+sys.argv[0]+" [config file] [start|stop|restart]\n") | ||
| 196 | sys.exit(1) | ||
| 197 | |||
| 198 | if not os.path.exists(sys.argv[1]): | ||
| 199 | sys.stderr.write("Error: config file \"" + sys.argv[1] + "\" was not found!\n") | ||
| 200 | sys.exit(1) | ||
| 201 | |||
| 202 | command = sys.argv[2] | ||
| 203 | command_options = ["start", "stop", "restart"] | ||
| 204 | if not command in command_options: | ||
| 205 | sys.stderr.write("Usage: "+sys.argv[0]+" [config file] [start|stop|restart]\n") | ||
| 206 | sys.exit(1) | ||
| 207 | |||
| 208 | Config = ConfigParser.ConfigParser() | ||
| 209 | Config.read(sys.argv[1]) | ||
| 210 | |||
| 211 | network_addr = getConfig(Config, "main", "network") | ||
| 212 | getConfig(Config, "main", "auto_destroy") | ||
| 213 | auto_destroy = Config.getboolean("main", "auto_destroy") | ||
| 214 | getConfig(Config, "main", "auto_assign_ip") | ||
| 215 | auto_assign_ip = Config.getboolean("main", "auto_assign_ip") | ||
| 216 | network_name = 'ops_default' | ||
| 217 | uri = 'qemu:///system' | ||
| 218 | |||
| 219 | # Connect to libvirt | ||
| 220 | conn = libvirt.open(uri) | ||
| 221 | if conn is None: | ||
| 222 | print( "Failed to open connection to the hypervisor" ) | ||
| 223 | exit(1) | ||
| 224 | |||
| 225 | if command == "start": | ||
| 226 | destroyNetwork(conn, network_name) | ||
| 227 | |||
| 228 | # Change the default bridge device from virbr0 to virbr%d. | ||
| 229 | # This will make libvirt try virbr0, virbr1, etc. until it finds a free one. | ||
| 230 | cnt = 0 | ||
| 231 | ifaces = networkInterfaces() | ||
| 232 | found_virbr = False | ||
| 233 | while found_virbr == False: | ||
| 234 | if cnt > 254: | ||
| 235 | print( "Giving up on looking for a free virbr network interface!" ) | ||
| 236 | exit(1) | ||
| 237 | bridge_nw_interface = 'virbr' + str(cnt) | ||
| 238 | if bridge_nw_interface not in ifaces: | ||
| 239 | print( "bridge_nw_interface: %s" % bridge_nw_interface ) | ||
| 240 | network_spec = make_nw_spec(network_name, bridge_nw_interface, network_addr, auto_assign_ip) | ||
| 241 | try: | ||
| 242 | conn.networkDefineXML(network_spec) | ||
| 243 | nw = conn.networkLookupByName(network_name) | ||
| 244 | nw.create() | ||
| 245 | found_virbr = True | ||
| 246 | except: | ||
| 247 | print( "Network Name: %s" % network_name ) | ||
| 248 | destroyNetwork( conn, network_name ) | ||
| 249 | print( "Error creating network interface" ) | ||
| 250 | cnt += 1 | ||
| 251 | else: | ||
| 252 | # verify network exists | ||
| 253 | try: | ||
| 254 | nw = conn.networkLookupByName(network_name) | ||
| 255 | except: | ||
| 256 | print( "Error! Virtual network " + network_name + " is not defined!" ) | ||
| 257 | exit(1) | ||
| 258 | if not nw.isActive(): | ||
| 259 | print( "Error! Virtual network " + network_name + " is not running!" ) | ||
| 260 | exit(1) | ||
| 261 | |||
| 262 | emulator = getConfig(Config, "main", "emulator") | ||
| 263 | if not os.path.exists(emulator): | ||
| 264 | print( "Emulator %s does not exist!" % emulator ) | ||
| 265 | exit(1) | ||
| 266 | |||
| 267 | controller_name = 'controller' | ||
| 268 | if command == "start": | ||
| 269 | # Define the controller xml | ||
| 270 | controller_kernel = getConfig(Config, "controller", "kernel") | ||
| 271 | controller_disk = getConfig(Config, "controller", "disk") | ||
| 272 | |||
| 273 | controller_ip = None | ||
| 274 | if not auto_assign_ip: | ||
| 275 | controller_ip = getConfig(Config, "controller", "ip") | ||
| 276 | controller_spec = make_spec(controller_name, network_addr, controller_kernel, | ||
| 277 | controller_disk, bridge_nw_interface, emulator, | ||
| 278 | auto_assign_ip, controller_ip) | ||
| 279 | |||
| 280 | # Now that network is setup let's actually run the virtual images | ||
| 281 | startDomain(conn, auto_destroy, controller_name, controller_spec) | ||
| 282 | elif command == "stop": | ||
| 283 | destroyDomain(conn, True, controller_name) | ||
| 284 | elif command == "restart": | ||
| 285 | restartDomain(conn, controller_name) | ||
| 286 | |||
| 287 | for i in Config.sections(): | ||
| 288 | if i.startswith("compute"): | ||
| 289 | if command == "start": | ||
| 290 | # Define the compute xml | ||
| 291 | kernel = getConfig(Config, i, "kernel") | ||
| 292 | disk = getConfig(Config, i, "disk") | ||
| 293 | compute_ip = None | ||
| 294 | if not auto_assign_ip: | ||
| 295 | compute_ip = getConfig(Config, i, "ip") | ||
| 296 | spec = make_spec(i, network_addr, kernel, disk, bridge_nw_interface, | ||
| 297 | emulator, auto_assign_ip, compute_ip) | ||
| 298 | startDomain(conn, auto_destroy, i, spec) | ||
| 299 | elif command == "stop": | ||
| 300 | destroyDomain(conn, True, i) | ||
| 301 | elif command == "restart": | ||
| 302 | restartDomain(conn, i) | ||
| 303 | |||
| 304 | conn.close() | ||
