| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 """ | 2 """ |
| 3 Utility classes and functions to handle Virtual Machine creation using qemu. | 3 Utility classes and functions to handle Virtual Machine creation using qemu. |
| 4 | 4 |
| 5 @copyright: 2008-2009 Red Hat Inc. | 5 @copyright: 2008-2009 Red Hat Inc. |
| 6 """ | 6 """ |
| 7 | 7 |
| 8 import time, os, logging, fcntl, re, commands, glob | 8 import time, os, logging, fcntl, re, commands, glob |
| 9 import kvm_utils, kvm_subprocess, kvm_monitor | 9 import kvm_utils, kvm_subprocess, kvm_monitor |
| 10 from autotest_lib.client.common_lib import error | 10 from autotest_lib.client.common_lib import error |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 if state: | 318 if state: |
| 319 self.__dict__ = state | 319 self.__dict__ = state |
| 320 else: | 320 else: |
| 321 self.process = None | 321 self.process = None |
| 322 self.serial_console = None | 322 self.serial_console = None |
| 323 self.redirs = {} | 323 self.redirs = {} |
| 324 self.vnc_port = 5900 | 324 self.vnc_port = 5900 |
| 325 self.monitors = [] | 325 self.monitors = [] |
| 326 self.pci_assignable = None | 326 self.pci_assignable = None |
| 327 self.netdev_id = [] | 327 self.netdev_id = [] |
| 328 self.device_id = [] |
| 328 self.uuid = None | 329 self.uuid = None |
| 329 | 330 |
| 330 # Find a unique identifier for this VM | 331 # Find a unique identifier for this VM |
| 331 while True: | 332 while True: |
| 332 self.instance = (time.strftime("%Y%m%d-%H%M%S-") + | 333 self.instance = (time.strftime("%Y%m%d-%H%M%S-") + |
| 333 kvm_utils.generate_random_string(4)) | 334 kvm_utils.generate_random_string(4)) |
| 334 if not glob.glob("/tmp/*%s" % self.instance): | 335 if not glob.glob("/tmp/*%s" % self.instance): |
| 335 break | 336 break |
| 336 | 337 |
| 337 self.name = name | 338 self.name = name |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 if werror: | 455 if werror: |
| 455 cmd += ",werror=%s" % werror | 456 cmd += ",werror=%s" % werror |
| 456 if serial: | 457 if serial: |
| 457 cmd += ",serial='%s'" % serial | 458 cmd += ",serial='%s'" % serial |
| 458 if snapshot: | 459 if snapshot: |
| 459 cmd += ",snapshot=on" | 460 cmd += ",snapshot=on" |
| 460 if boot: | 461 if boot: |
| 461 cmd += ",boot=on" | 462 cmd += ",boot=on" |
| 462 return cmd | 463 return cmd |
| 463 | 464 |
| 464 def add_nic(help, vlan, model=None, mac=None, netdev_id=None, | 465 def add_nic(help, vlan, model=None, mac=None, device_id=None, netdev_id=
None, |
| 465 nic_extra_params=None): | 466 nic_extra_params=None): |
| 466 if has_option(help, "netdev"): | 467 if has_option(help, "netdev"): |
| 467 netdev_vlan_str = ",netdev=%s" % netdev_id | 468 netdev_vlan_str = ",netdev=%s" % netdev_id |
| 468 else: | 469 else: |
| 469 netdev_vlan_str = ",vlan=%d" % vlan | 470 netdev_vlan_str = ",vlan=%d" % vlan |
| 470 if has_option(help, "device"): | 471 if has_option(help, "device"): |
| 471 if not model: | 472 if not model: |
| 472 model = "rtl8139" | 473 model = "rtl8139" |
| 473 elif model == "virtio": | 474 elif model == "virtio": |
| 474 model = "virtio-net-pci" | 475 model = "virtio-net-pci" |
| 475 cmd = " -device %s" % model + netdev_vlan_str | 476 cmd = " -device %s" % model + netdev_vlan_str |
| 476 if mac: | 477 if mac: |
| 477 cmd += ",mac='%s'" % mac | 478 cmd += ",mac='%s'" % mac |
| 478 if nic_extra_params: | 479 if nic_extra_params: |
| 479 cmd += ",%s" % nic_extra_params | 480 cmd += ",%s" % nic_extra_params |
| 480 else: | 481 else: |
| 481 cmd = " -net nic" + netdev_vlan_str | 482 cmd = " -net nic" + netdev_vlan_str |
| 482 if model: | 483 if model: |
| 483 cmd += ",model=%s" % model | 484 cmd += ",model=%s" % model |
| 484 if mac: | 485 if mac: |
| 485 cmd += ",macaddr='%s'" % mac | 486 cmd += ",macaddr='%s'" % mac |
| 487 if device_id: |
| 488 cmd += ",id='%s'" % device_id |
| 486 return cmd | 489 return cmd |
| 487 | 490 |
| 488 def add_net(help, vlan, mode, ifname=None, script=None, | 491 def add_net(help, vlan, mode, ifname=None, script=None, |
| 489 downscript=None, tftp=None, bootfile=None, hostfwd=[], | 492 downscript=None, tftp=None, bootfile=None, hostfwd=[], |
| 490 netdev_id=None, netdev_extra_params=None): | 493 netdev_id=None, netdev_extra_params=None): |
| 491 if has_option(help, "netdev"): | 494 if has_option(help, "netdev"): |
| 492 cmd = " -netdev %s,id=%s" % (mode, netdev_id) | 495 cmd = " -netdev %s,id=%s" % (mode, netdev_id) |
| 493 if netdev_extra_params: | 496 if netdev_extra_params: |
| 494 cmd += ",%s" % netdev_extra_params | 497 cmd += ",%s" % netdev_extra_params |
| 495 else: | 498 else: |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 redir_params = params.object_params(redir_name) | 631 redir_params = params.object_params(redir_name) |
| 629 guest_port = int(redir_params.get("guest_port")) | 632 guest_port = int(redir_params.get("guest_port")) |
| 630 host_port = vm.redirs.get(guest_port) | 633 host_port = vm.redirs.get(guest_port) |
| 631 redirs += [(host_port, guest_port)] | 634 redirs += [(host_port, guest_port)] |
| 632 | 635 |
| 633 vlan = 0 | 636 vlan = 0 |
| 634 for nic_name in params.objects("nics"): | 637 for nic_name in params.objects("nics"): |
| 635 nic_params = params.object_params(nic_name) | 638 nic_params = params.object_params(nic_name) |
| 636 try: | 639 try: |
| 637 netdev_id = vm.netdev_id[vlan] | 640 netdev_id = vm.netdev_id[vlan] |
| 641 device_id = vm.device_id[vlan] |
| 638 except IndexError: | 642 except IndexError: |
| 639 netdev_id = None | 643 netdev_id = None |
| 640 # Handle the '-net nic' part | 644 # Handle the '-net nic' part |
| 641 mac = vm.get_mac_address(vlan) | 645 try: |
| 646 mac = vm.get_mac_address(vlan) |
| 647 except VMAddressError: |
| 648 mac = None |
| 642 qemu_cmd += add_nic(help, vlan, nic_params.get("nic_model"), mac, | 649 qemu_cmd += add_nic(help, vlan, nic_params.get("nic_model"), mac, |
| 643 netdev_id, nic_params.get("nic_extra_params")) | 650 device_id, netdev_id, nic_params.get("nic_extra_
params")) |
| 644 # Handle the '-net tap' or '-net user' part | 651 # Handle the '-net tap' or '-net user' or '-netdev' part |
| 645 script = nic_params.get("nic_script") | 652 script = nic_params.get("nic_script") |
| 646 downscript = nic_params.get("nic_downscript") | 653 downscript = nic_params.get("nic_downscript") |
| 647 tftp = nic_params.get("tftp") | 654 tftp = nic_params.get("tftp") |
| 648 if script: | 655 if script: |
| 649 script = kvm_utils.get_path(root_dir, script) | 656 script = kvm_utils.get_path(root_dir, script) |
| 650 if downscript: | 657 if downscript: |
| 651 downscript = kvm_utils.get_path(root_dir, downscript) | 658 downscript = kvm_utils.get_path(root_dir, downscript) |
| 652 if tftp: | 659 if tftp: |
| 653 tftp = kvm_utils.get_path(root_dir, tftp) | 660 tftp = kvm_utils.get_path(root_dir, tftp) |
| 654 qemu_cmd += add_net(help, vlan, nic_params.get("nic_mode", "user"), | 661 qemu_cmd += add_net(help, vlan, nic_params.get("nic_mode", "user"), |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 try: | 827 try: |
| 821 # Handle port redirections | 828 # Handle port redirections |
| 822 redir_names = params.objects("redirs") | 829 redir_names = params.objects("redirs") |
| 823 host_ports = kvm_utils.find_free_ports(5000, 6000, len(redir_names)) | 830 host_ports = kvm_utils.find_free_ports(5000, 6000, len(redir_names)) |
| 824 self.redirs = {} | 831 self.redirs = {} |
| 825 for i in range(len(redir_names)): | 832 for i in range(len(redir_names)): |
| 826 redir_params = params.object_params(redir_names[i]) | 833 redir_params = params.object_params(redir_names[i]) |
| 827 guest_port = int(redir_params.get("guest_port")) | 834 guest_port = int(redir_params.get("guest_port")) |
| 828 self.redirs[guest_port] = host_ports[i] | 835 self.redirs[guest_port] = host_ports[i] |
| 829 | 836 |
| 830 # Generate netdev IDs for all NICs | 837 # Generate netdev/device IDs for all NICs |
| 831 self.netdev_id = [] | 838 self.netdev_id = [] |
| 839 self.device_id = [] |
| 832 for nic in params.objects("nics"): | 840 for nic in params.objects("nics"): |
| 833 self.netdev_id.append(kvm_utils.generate_random_id()) | 841 self.netdev_id.append(kvm_utils.generate_random_id()) |
| 842 self.device_id.append(kvm_utils.generate_random_id()) |
| 834 | 843 |
| 835 # Find available VNC port, if needed | 844 # Find available VNC port, if needed |
| 836 if params.get("display") == "vnc": | 845 if params.get("display") == "vnc": |
| 837 self.vnc_port = kvm_utils.find_free_port(5900, 6100) | 846 self.vnc_port = kvm_utils.find_free_port(5900, 6100) |
| 838 | 847 |
| 839 # Find random UUID if specified 'uuid = random' in config file | 848 # Find random UUID if specified 'uuid = random' in config file |
| 840 if params.get("uuid") == "random": | 849 if params.get("uuid") == "random": |
| 841 f = open("/proc/sys/kernel/random/uuid") | 850 f = open("/proc/sys/kernel/random/uuid") |
| 842 self.uuid = f.read().strip() | 851 self.uuid = f.read().strip() |
| 843 f.close() | 852 f.close() |
| 844 | 853 |
| 845 # Generate or copy MAC addresses for all NICs | 854 # Generate or copy MAC addresses for all NICs |
| 846 num_nics = len(params.objects("nics")) | 855 num_nics = len(params.objects("nics")) |
| 847 for vlan in range(num_nics): | 856 for vlan in range(num_nics): |
| 848 nic_name = params.objects("nics")[vlan] | 857 nic_name = params.objects("nics")[vlan] |
| 849 nic_params = params.object_params(nic_name) | 858 nic_params = params.object_params(nic_name) |
| 850 if nic_params.get("nic_mac", None): | 859 mac = (nic_params.get("nic_mac") or |
| 851 mac = nic_params.get("nic_mac") | 860 mac_source and mac_source.get_mac_address(vlan)) |
| 861 if mac: |
| 852 kvm_utils.set_mac_address(self.instance, vlan, mac) | 862 kvm_utils.set_mac_address(self.instance, vlan, mac) |
| 853 else: | 863 else: |
| 854 mac = mac_source and mac_source.get_mac_address(vlan) | 864 kvm_utils.generate_mac_address(self.instance, vlan) |
| 855 if mac: | |
| 856 kvm_utils.set_mac_address(self.instance, vlan, mac) | |
| 857 else: | |
| 858 kvm_utils.generate_mac_address(self.instance, vlan) | |
| 859 | 865 |
| 860 # Assign a PCI assignable device | 866 # Assign a PCI assignable device |
| 861 self.pci_assignable = None | 867 self.pci_assignable = None |
| 862 pa_type = params.get("pci_assignable") | 868 pa_type = params.get("pci_assignable") |
| 863 if pa_type and pa_type != "no": | 869 if pa_type and pa_type != "no": |
| 864 pa_devices_requested = params.get("devices_requested") | 870 pa_devices_requested = params.get("devices_requested") |
| 865 | 871 |
| 866 # Virtual Functions (VF) assignable devices | 872 # Virtual Functions (VF) assignable devices |
| 867 if pa_type == "vf": | 873 if pa_type == "vf": |
| 868 self.pci_assignable = kvm_utils.PciAssignable( | 874 self.pci_assignable = kvm_utils.PciAssignable( |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1200 nic_params = self.params.object_params(nic_name) | 1206 nic_params = self.params.object_params(nic_name) |
| 1201 if nic_params.get("nic_mode") == "tap": | 1207 if nic_params.get("nic_mode") == "tap": |
| 1202 return port | 1208 return port |
| 1203 else: | 1209 else: |
| 1204 try: | 1210 try: |
| 1205 return self.redirs[port] | 1211 return self.redirs[port] |
| 1206 except KeyError: | 1212 except KeyError: |
| 1207 raise VMPortNotRedirectedError(port) | 1213 raise VMPortNotRedirectedError(port) |
| 1208 | 1214 |
| 1209 | 1215 |
| 1216 def get_peer(self, netid): |
| 1217 """ |
| 1218 Return the peer of netdev or network deivce. |
| 1219 |
| 1220 @param netid: id of netdev or device |
| 1221 @return: id of the peer device otherwise None |
| 1222 """ |
| 1223 network_info = self.monitor.info("network") |
| 1224 try: |
| 1225 return re.findall("%s:.*peer=(.*)" % netid, network_info)[0] |
| 1226 except IndexError: |
| 1227 return None |
| 1228 |
| 1229 |
| 1210 def get_ifname(self, nic_index=0): | 1230 def get_ifname(self, nic_index=0): |
| 1211 """ | 1231 """ |
| 1212 Return the ifname of a tap device associated with a NIC. | 1232 Return the ifname of a tap device associated with a NIC. |
| 1213 | 1233 |
| 1214 @param nic_index: Index of the NIC | 1234 @param nic_index: Index of the NIC |
| 1215 """ | 1235 """ |
| 1216 nics = self.params.objects("nics") | 1236 nics = self.params.objects("nics") |
| 1217 nic_name = nics[nic_index] | 1237 nic_name = nics[nic_index] |
| 1218 nic_params = self.params.object_params(nic_name) | 1238 nic_params = self.params.object_params(nic_name) |
| 1219 if nic_params.get("nic_ifname"): | 1239 if nic_params.get("nic_ifname"): |
| 1220 return nic_params.get("nic_ifname") | 1240 return nic_params.get("nic_ifname") |
| 1221 else: | 1241 else: |
| 1222 return "t%d-%s" % (nic_index, self.instance[-11:]) | 1242 return "t%d-%s" % (nic_index, self.instance[-11:]) |
| 1223 | 1243 |
| 1224 | 1244 |
| 1225 def get_mac_address(self, nic_index=0): | 1245 def get_mac_address(self, nic_index=0): |
| 1226 """ | 1246 """ |
| 1227 Return the MAC address of a NIC. | 1247 Return the MAC address of a NIC. |
| 1228 | 1248 |
| 1229 @param nic_index: Index of the NIC | 1249 @param nic_index: Index of the NIC |
| 1230 @raise VMMACAddressMissingError: If no MAC address is defined for the | 1250 @raise VMMACAddressMissingError: If no MAC address is defined for the |
| 1231 requested NIC | 1251 requested NIC |
| 1232 """ | 1252 """ |
| 1233 mac = kvm_utils.get_mac_address(self.instance, nic_index) | 1253 nic_name = self.params.objects("nics")[nic_index] |
| 1254 nic_params = self.params.object_params(nic_name) |
| 1255 mac = (nic_params.get("nic_mac") or |
| 1256 kvm_utils.get_mac_address(self.instance, nic_index)) |
| 1234 if not mac: | 1257 if not mac: |
| 1235 raise VMMACAddressMissingError(nic_index) | 1258 raise VMMACAddressMissingError(nic_index) |
| 1236 return mac | 1259 return mac |
| 1237 | 1260 |
| 1238 | 1261 |
| 1239 def free_mac_address(self, nic_index=0): | 1262 def free_mac_address(self, nic_index=0): |
| 1240 """ | 1263 """ |
| 1241 Free a NIC's MAC address. | 1264 Free a NIC's MAC address. |
| 1242 | 1265 |
| 1243 @param nic_index: Index of the NIC | 1266 @param nic_index: Index of the NIC |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1745 Save the state of virtual machine to a file through migrate to | 1768 Save the state of virtual machine to a file through migrate to |
| 1746 exec | 1769 exec |
| 1747 """ | 1770 """ |
| 1748 # Make sure we only get one iteration | 1771 # Make sure we only get one iteration |
| 1749 self.monitor.cmd("migrate_set_speed 1000g") | 1772 self.monitor.cmd("migrate_set_speed 1000g") |
| 1750 self.monitor.cmd("migrate_set_downtime 100000000") | 1773 self.monitor.cmd("migrate_set_downtime 100000000") |
| 1751 self.monitor.migrate('"exec:cat>%s"' % path) | 1774 self.monitor.migrate('"exec:cat>%s"' % path) |
| 1752 # Restore the speed and downtime of migration | 1775 # Restore the speed and downtime of migration |
| 1753 self.monitor.cmd("migrate_set_speed %d" % (32<<20)) | 1776 self.monitor.cmd("migrate_set_speed %d" % (32<<20)) |
| 1754 self.monitor.cmd("migrate_set_downtime 0.03") | 1777 self.monitor.cmd("migrate_set_downtime 0.03") |
| OLD | NEW |