Revision af2f716d
b/lib/hypervisor/hv_kvm.py | ||
---|---|---|
1965 | 1965 |
if not match: |
1966 | 1966 |
raise errors.HotplugError("Try hotplug only in running instances.") |
1967 | 1967 |
v_major, v_min, _, _ = match.groups() |
1968 |
if (v_major, v_min) < (1, 0):
|
|
1968 |
if (int(v_major), int(v_min)) < (1, 0):
|
|
1969 | 1969 |
raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0") |
1970 | 1970 |
|
1971 | 1971 |
if dev_type == constants.HOTPLUG_TARGET_DISK: |
... | ... | |
1991 | 1991 |
for line in output.stdout.splitlines(): |
1992 | 1992 |
logging.info("%s", line) |
1993 | 1993 |
|
1994 |
def HotAddDevice(self, instance, dev_type, device, extra, seq): |
|
1995 |
""" Helper method to hot-add a new device |
|
1996 |
|
|
1997 |
It gets free pci slot generates the device name and invokes the |
|
1998 |
device specific method. |
|
1999 |
|
|
2000 |
""" |
|
2001 |
# in case of hot-mod this is given |
|
2002 |
if device.pci is None: |
|
2003 |
self._GetFreePCISlot(instance, device) |
|
2004 |
kvm_devid = _GenerateDeviceKVMId(dev_type, device) |
|
2005 |
runtime = self._LoadKVMRuntime(instance) |
|
2006 |
if dev_type == constants.HOTPLUG_TARGET_DISK: |
|
2007 |
command = "drive_add dummy file=%s,if=none,id=%s,format=raw\n" % \ |
|
2008 |
(extra, kvm_devid) |
|
2009 |
command += ("device_add virtio-blk-pci,bus=pci.0,addr=%s,drive=%s,id=%s" % |
|
2010 |
(hex(device.pci), kvm_devid, kvm_devid)) |
|
2011 |
elif dev_type == constants.HOTPLUG_TARGET_NIC: |
|
2012 |
(tap, fd) = _OpenTap() |
|
2013 |
self._ConfigureNIC(instance, seq, device, tap) |
|
2014 |
self._PassTapFd(instance, fd, device) |
|
2015 |
command = "netdev_add tap,id=%s,fd=%s\n" % (kvm_devid, kvm_devid) |
|
2016 |
args = "virtio-net-pci,bus=pci.0,addr=%s,mac=%s,netdev=%s,id=%s" % \ |
|
2017 |
(hex(device.pci), device.mac, kvm_devid, kvm_devid) |
|
2018 |
command += "device_add %s" % args |
|
2019 |
utils.WriteFile(self._InstanceNICFile(instance.name, seq), data=tap) |
|
2020 |
|
|
2021 |
self._CallHotplugCommand(instance.name, command) |
|
2022 |
# update relevant entries in runtime file |
|
2023 |
index = _DEVICE_RUNTIME_INDEX[dev_type] |
|
2024 |
entry = _RUNTIME_ENTRY[dev_type](device, extra) |
|
2025 |
runtime[index].append(entry) |
|
2026 |
self._SaveKVMRuntime(instance, runtime) |
|
2027 |
|
|
2028 |
def HotDelDevice(self, instance, dev_type, device, _, seq): |
|
2029 |
""" Helper method for hot-del device |
|
2030 |
|
|
2031 |
It gets device info from runtime file, generates the device name and |
|
2032 |
invokes the device specific method. |
|
2033 |
|
|
2034 |
""" |
|
2035 |
runtime = self._LoadKVMRuntime(instance) |
|
2036 |
entry = _GetExistingDeviceInfo(dev_type, device, runtime) |
|
2037 |
kvm_device = _RUNTIME_DEVICE[dev_type](entry) |
|
2038 |
kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device) |
|
2039 |
if dev_type == constants.HOTPLUG_TARGET_DISK: |
|
2040 |
command = "device_del %s" % kvm_devid |
|
2041 |
elif dev_type == constants.HOTPLUG_TARGET_NIC: |
|
2042 |
command = "device_del %s\n" % kvm_devid |
|
2043 |
command += "netdev_del %s" % kvm_devid |
|
2044 |
utils.RemoveFile(self._InstanceNICFile(instance.name, seq)) |
|
2045 |
self._CallHotplugCommand(instance.name, command) |
|
2046 |
index = _DEVICE_RUNTIME_INDEX[dev_type] |
|
2047 |
runtime[index].remove(entry) |
|
2048 |
self._SaveKVMRuntime(instance, runtime) |
|
2049 |
|
|
2050 |
return kvm_device.pci |
|
2051 |
|
|
2052 |
def HotModDevice(self, instance, dev_type, device, _, seq): |
|
2053 |
""" Helper method for hot-mod device |
|
2054 |
|
|
2055 |
It gets device info from runtime file, generates the device name and |
|
2056 |
invokes the device specific method. Currently only NICs support hot-mod |
|
2057 |
|
|
2058 |
""" |
|
2059 |
if dev_type == constants.HOTPLUG_TARGET_NIC: |
|
2060 |
# putting it back in the same pci slot |
|
2061 |
device.pci = self.HotDelDevice(instance, dev_type, device, _, seq) |
|
2062 |
# TODO: remove sleep when socat gets removed |
|
2063 |
time.sleep(2) |
|
2064 |
self.HotAddDevice(instance, dev_type, device, _, seq) |
|
2065 |
|
|
2066 |
def _PassTapFd(self, instance, fd, nic): |
|
2067 |
"""Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS |
|
2068 |
|
|
2069 |
""" |
|
2070 |
# TODO: factor out code related to unix sockets. |
|
2071 |
# squash common parts between monitor and qmp |
|
2072 |
kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic) |
|
2073 |
command = "getfd %s\n" % kvm_devid |
|
2074 |
fds = [fd] |
|
2075 |
logging.info("%s", fds) |
|
2076 |
try: |
|
2077 |
monsock = MonitorSocket(self._InstanceMonitor(instance.name)) |
|
2078 |
monsock.connect() |
|
2079 |
fdsend.sendfds(monsock.sock, command, fds=fds) |
|
2080 |
finally: |
|
2081 |
monsock.close() |
|
2082 |
|
|
1994 | 2083 |
@classmethod |
1995 | 2084 |
def _ParseKVMVersion(cls, text): |
1996 | 2085 |
"""Parse the KVM version from the --help output. |
Also available in: Unified diff