Revision 2435f63b lib/hypervisor/hv_kvm.py
b/lib/hypervisor/hv_kvm.py | ||
---|---|---|
38 | 38 |
import stat |
39 | 39 |
import StringIO |
40 | 40 |
import fdsend |
41 |
from bitarray import bitarray |
|
41 | 42 |
try: |
42 | 43 |
import affinity # pylint: disable=F0401 |
43 | 44 |
except ImportError: |
... | ... | |
68 | 69 |
IFF_NO_PI = 0x1000 |
69 | 70 |
IFF_VNET_HDR = 0x4000 |
70 | 71 |
|
72 |
FREE = bitarray("0") |
|
71 | 73 |
|
72 | 74 |
def _ProbeTapVnetHdr(fd): |
73 | 75 |
"""Check whether to enable the IFF_VNET_HDR flag. |
... | ... | |
512 | 514 |
_CPU_INFO_CMD = "info cpus" |
513 | 515 |
_CONT_CMD = "cont" |
514 | 516 |
|
517 |
_INFO_PCI_RE = re.compile(r'Bus.*device[ ]*(\d+).*') |
|
518 |
_INFO_PCI_CMD = "info pci" |
|
519 |
|
|
520 |
|
|
515 | 521 |
ANCILLARY_FILES = [ |
516 | 522 |
_KVM_NETWORK_SCRIPT, |
517 | 523 |
] |
... | ... | |
990 | 996 |
boot_val = ",boot=on" |
991 | 997 |
drive_val = "file=%s,format=raw%s%s" % \ |
992 | 998 |
(dev_path, boot_val, cache_val) |
993 |
if cfdev.pci:
|
|
999 |
if cfdev.idx is not None:
|
|
994 | 1000 |
#TODO: name id after model |
995 |
drive_val += (",bus=0,unit=%d,if=none,id=drive%d" % |
|
996 |
(cfdev.pci, cfdev.idx)) |
|
1001 |
drive_val += (",if=none,id=drive%d" % cfdev.idx) |
|
1002 |
if cfdev.pci is not None: |
|
1003 |
drive_val += (",bus=0,unit=%d" % cfdev.pci) |
|
997 | 1004 |
else: |
998 | 1005 |
drive_val += if_val |
999 | 1006 |
|
1000 | 1007 |
kvm_cmd.extend(["-drive", drive_val]) |
1001 | 1008 |
|
1002 |
if cfdev.pci: |
|
1003 |
dev_val = ("%s,bus=pci.0,addr=%s,drive=drive%d,id=virtio-blk-pci.%d" % |
|
1004 |
(disk_model, hex(cfdev.pci), cfdev.idx, cfdev.idx)) |
|
1009 |
if cfdev.idx is not None: |
|
1010 |
dev_val = ("%s,drive=drive%d,id=virtio-blk-pci.%d" % |
|
1011 |
(disk_model, cfdev.idx, cfdev.idx)) |
|
1012 |
if cfdev.pci is not None: |
|
1013 |
dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci) |
|
1005 | 1014 |
kvm_cmd.extend(["-device", dev_val]) |
1006 | 1015 |
|
1007 | 1016 |
return kvm_cmd |
... | ... | |
1465 | 1474 |
tapfds.append(tapfd) |
1466 | 1475 |
taps.append(tapname) |
1467 | 1476 |
if (v_major, v_min) >= (0, 12): |
1468 |
if nic.pci: |
|
1469 |
nic_idx = nic.idx |
|
1477 |
nic_val = "%s,mac=%s" % (nic_model, nic.mac) |
|
1478 |
if nic.idx: |
|
1479 |
nic_val += (",netdev=netdev%d,id=virtio-net-pci.%d" % |
|
1480 |
(nic.idx, nic.idx)) |
|
1481 |
if nic.pci is not None: |
|
1482 |
nic_val += (",bus=pci.0,addr=%s" % hex(nic.pci)) |
|
1470 | 1483 |
else: |
1471 |
nic_idx = nic_seq |
|
1472 |
nic_val = ("%s,mac=%s,netdev=netdev%d" % |
|
1473 |
(nic_model, nic.mac, nic_idx)) |
|
1474 |
if nic.pci: |
|
1475 |
nic_val += (",bus=pci.0,addr=%s,id=virtio-net-pci.%d" % |
|
1476 |
(hex(nic.pci), nic_idx)) |
|
1477 |
tap_val = "type=tap,id=netdev%d,fd=%d%s" % (nic_idx, tapfd, tap_extra) |
|
1484 |
nic_val += (",netdev=netdev%d,id=virtio-net-pci.%d" % |
|
1485 |
(nic_seq, nic_seq)) |
|
1486 |
tap_val = ("type=tap,id=netdev%d,fd=%d%s" % |
|
1487 |
(nic.idx or nic_seq, tapfd, tap_extra)) |
|
1478 | 1488 |
kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val]) |
1479 | 1489 |
else: |
1480 | 1490 |
nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq, |
... | ... | |
1625 | 1635 |
|
1626 | 1636 |
return result |
1627 | 1637 |
|
1638 |
def _FindFreePCISlot(self, instance_name): |
|
1639 |
slots = bitarray(32) |
|
1640 |
slots.setall(False) |
|
1641 |
output = self._CallMonitorCommand(instance_name, self._INFO_PCI_CMD) |
|
1642 |
for line in output.stdout.splitlines(): |
|
1643 |
match = self._INFO_PCI_RE.search(line) |
|
1644 |
if match: |
|
1645 |
slot = int(match.group(1)) |
|
1646 |
slots[slot] = True |
|
1647 |
|
|
1648 |
free = slots.search(FREE, 1) |
|
1649 |
if not free: |
|
1650 |
raise errors.HypervisorError("All PCI slots occupied") |
|
1651 |
|
|
1652 |
return int(free[0]) |
|
1653 |
|
|
1654 |
def _HotplugEnabled(self, instance_name): |
|
1655 |
if not self._InstancePidAlive(instance_name)[2]: |
|
1656 |
logging.info("Cannot hotplug. Instance %s not alive", instance_name) |
|
1657 |
return False |
|
1658 |
|
|
1659 |
_, v_major, v_min, _ = self._GetKVMVersion() |
|
1660 |
return (v_major, v_min) >= (1, 0) |
|
1661 |
|
|
1628 | 1662 |
def HotAddDisk(self, instance, disk, dev_path, _): |
1629 | 1663 |
"""Hotadd new disk to the VM |
1630 | 1664 |
|
1631 | 1665 |
""" |
1632 |
if not self._InstancePidAlive(instance.name)[2]: |
|
1633 |
logging.info("Cannot hotplug. Instance %s not alive", instance.name) |
|
1634 |
return disk.ToDict() |
|
1635 |
|
|
1636 |
_, v_major, v_min, _ = self._GetKVMVersion() |
|
1637 |
if (v_major, v_min) >= (1, 0) and disk.pci: |
|
1666 |
if self._HotplugEnabled(instance.name): |
|
1667 |
disk.pci = self._FindFreePCISlot(instance.name) |
|
1638 | 1668 |
idx = disk.idx |
1639 | 1669 |
command = ("drive_add dummy file=%s,if=none,id=drive%d,format=raw" % |
1640 | 1670 |
(dev_path, idx)) |
... | ... | |
1656 | 1686 |
new_kvm_runtime = (kvm_cmd, kvm_nics, hvparams, block_devices) |
1657 | 1687 |
self._SaveKVMRuntime(instance, new_kvm_runtime) |
1658 | 1688 |
|
1659 |
return disk.ToDict()
|
|
1689 |
return disk.pci
|
|
1660 | 1690 |
|
1661 | 1691 |
def HotDelDisk(self, instance, disk, _): |
1662 | 1692 |
"""Hotdel disk to the VM |
1663 | 1693 |
|
1664 | 1694 |
""" |
1665 |
if not self._InstancePidAlive(instance.name)[2]: |
|
1666 |
logging.info("Cannot hotplug. Instance %s not alive", instance.name) |
|
1667 |
return disk.ToDict() |
|
1668 |
|
|
1669 |
_, v_major, v_min, _ = self._GetKVMVersion() |
|
1670 |
if (v_major, v_min) >= (1, 0) and disk.pci: |
|
1695 |
if self._HotplugEnabled(instance.name): |
|
1671 | 1696 |
idx = disk.idx |
1672 | 1697 |
|
1673 | 1698 |
command = "device_del virtio-blk-pci.%d" % idx |
... | ... | |
1693 | 1718 |
new_kvm_runtime = (kvm_cmd, kvm_nics, hvparams, block_devices) |
1694 | 1719 |
self._SaveKVMRuntime(instance, new_kvm_runtime) |
1695 | 1720 |
|
1696 |
return disk.ToDict() |
|
1697 |
|
|
1698 | 1721 |
def HotAddNic(self, instance, nic, seq): |
1699 | 1722 |
"""Hotadd new nic to the VM |
1700 | 1723 |
|
1701 | 1724 |
""" |
1702 |
if not self._InstancePidAlive(instance.name)[2]: |
|
1703 |
logging.info("Cannot hotplug. Instance %s not alive", instance.name) |
|
1704 |
return nic.ToDict() |
|
1705 |
|
|
1706 |
_, v_major, v_min, _ = self._GetKVMVersion() |
|
1707 |
if (v_major, v_min) >= (1, 0) and nic.pci: |
|
1725 |
if self._HotplugEnabled(instance.name): |
|
1726 |
nic.pci = self._FindFreePCISlot(instance.name) |
|
1708 | 1727 |
mac = nic.mac |
1709 | 1728 |
idx = nic.idx |
1710 | 1729 |
|
... | ... | |
1736 | 1755 |
new_kvm_runtime = (kvm_cmd, kvm_nics, hvparams, block_devices) |
1737 | 1756 |
self._SaveKVMRuntime(instance, new_kvm_runtime) |
1738 | 1757 |
|
1739 |
return nic.ToDict()
|
|
1758 |
return nic.pci
|
|
1740 | 1759 |
|
1741 | 1760 |
def HotDelNic(self, instance, nic, _): |
1742 | 1761 |
"""Hotadd new nic to the VM |
1743 | 1762 |
|
1744 | 1763 |
""" |
1745 |
if not self._InstancePidAlive(instance.name)[2]: |
|
1746 |
logging.info("Cannot hotplug. Instance %s not alive", instance.name) |
|
1747 |
return nic.ToDict() |
|
1748 |
|
|
1749 |
_, v_major, v_min, _ = self._GetKVMVersion() |
|
1750 |
if (v_major, v_min) >= (1, 0) and nic.pci: |
|
1764 |
if self._HotplugEnabled(instance.name): |
|
1751 | 1765 |
idx = nic.idx |
1752 | 1766 |
|
1753 | 1767 |
command = "device_del virtio-net-pci.%d" % idx |
... | ... | |
1772 | 1786 |
new_kvm_runtime = (kvm_cmd, kvm_nics, hvparams, block_devices) |
1773 | 1787 |
self._SaveKVMRuntime(instance, new_kvm_runtime) |
1774 | 1788 |
|
1775 |
return nic.ToDict() |
|
1776 | 1789 |
|
1777 | 1790 |
def _PassTapFd(self, instance, fd, nic): |
1778 | 1791 |
monsock = utils.ShellQuote(self._InstanceMonitor(instance.name)) |
Also available in: Unified diff