Revision 24711492
b/lib/backend.py | ||
---|---|---|
2003 | 2003 |
return fn(instance, dev_type, device, extra, seq) |
2004 | 2004 |
|
2005 | 2005 |
|
2006 |
def HotplugSupported(instance): |
|
2007 |
"""Checks if hotplug is generally supported. |
|
2008 |
|
|
2009 |
""" |
|
2010 |
hyper = hypervisor.GetHypervisor(instance.hypervisor) |
|
2011 |
try: |
|
2012 |
hyper.HotplugSupported(instance) |
|
2013 |
except errors.HotplugError, err: |
|
2014 |
_Fail("Hotplug is not supported: %s", err) |
|
2015 |
|
|
2016 |
|
|
2006 | 2017 |
def BlockdevCreate(disk, size, owner, on_primary, info, excl_stor): |
2007 | 2018 |
"""Creates a block device for an instance. |
2008 | 2019 |
|
b/lib/cmdlib/instance.py | ||
---|---|---|
2843 | 2843 |
# dictionary with instance information after the modification |
2844 | 2844 |
ispec = {} |
2845 | 2845 |
|
2846 |
if self.op.hotplug: |
|
2847 |
result = self.rpc.call_hotplug_supported(self.instance.primary_node, |
|
2848 |
self.instance) |
|
2849 |
result.Raise("Hotplug is not supported.") |
|
2850 |
|
|
2846 | 2851 |
# Prepare NIC modifications |
2847 | 2852 |
self.nicmod = _PrepareContainerMods(self.op.nics, _InstNicModPrivate) |
2848 | 2853 |
|
b/lib/hypervisor/hv_base.py | ||
---|---|---|
589 | 589 |
def VerifyHotplugSupport(self, instance, action, dev_type): |
590 | 590 |
"""Verifies that hotplug is supported. |
591 | 591 |
|
592 |
Hotplug is not supported by default. If a hypervisor wants to support
|
|
593 |
it it should override this method.
|
|
592 |
Given the target device and hotplug action checks if hotplug is
|
|
593 |
actually supported.
|
|
594 | 594 |
|
595 | 595 |
@type instance: L{objects.Instance} |
596 | 596 |
@param instance: the instance object |
... | ... | |
601 | 601 |
@raise errors.HotplugError: if hotplugging is not supported |
602 | 602 |
|
603 | 603 |
""" |
604 |
raise errors.HotplugError("Hotplug is not supported.") |
|
605 |
|
|
606 |
def HotplugSupported(self, instance): |
|
607 |
"""Checks if hotplug is supported. |
|
608 |
|
|
609 |
By default is not. Currently only KVM hypervisor supports it. |
|
610 |
|
|
611 |
""" |
|
604 | 612 |
raise errors.HotplugError("Hotplug is not supported by this hypervisor") |
b/lib/hypervisor/hv_kvm.py | ||
---|---|---|
2003 | 2003 |
"""Verifies that hotplug is supported. |
2004 | 2004 |
|
2005 | 2005 |
Hotplug is *not* supported in case of: |
2006 |
- qemu versions < 1.0 |
|
2007 | 2006 |
- security models and chroot (disk hotplug) |
2008 | 2007 |
- fdsend module is missing (nic hot-add) |
2009 | 2008 |
|
2010 | 2009 |
@raise errors.HypervisorError: in one of the previous cases |
2011 | 2010 |
|
2012 | 2011 |
""" |
2013 |
output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD) |
|
2014 |
# TODO: search for netdev_add, drive_add, device_add..... |
|
2015 |
match = self._INFO_VERSION_RE.search(output.stdout) |
|
2016 |
if not match: |
|
2017 |
raise errors.HotplugError("Try hotplug only in running instances.") |
|
2018 |
v_major, v_min, _, _ = match.groups() |
|
2019 |
if (int(v_major), int(v_min)) < (1, 0): |
|
2020 |
raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0") |
|
2021 |
|
|
2022 | 2012 |
if dev_type == constants.HOTPLUG_TARGET_DISK: |
2023 | 2013 |
hvp = instance.hvparams |
2024 | 2014 |
security_model = hvp[constants.HV_SECURITY_MODEL] |
... | ... | |
2035 | 2025 |
raise errors.HotplugError("Cannot hot-add NIC." |
2036 | 2026 |
" fdsend python module is missing.") |
2037 | 2027 |
|
2028 |
def HotplugSupported(self, instance): |
|
2029 |
"""Checks if hotplug is generally supported. |
|
2030 |
|
|
2031 |
Hotplug is *not* supported in case of: |
|
2032 |
- qemu versions < 1.0 |
|
2033 |
- for stopped instances |
|
2034 |
|
|
2035 |
@raise errors.HypervisorError: in one of the previous cases |
|
2036 |
|
|
2037 |
""" |
|
2038 |
output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD) |
|
2039 |
# TODO: search for netdev_add, drive_add, device_add..... |
|
2040 |
match = self._INFO_VERSION_RE.search(output.stdout) |
|
2041 |
if not match: |
|
2042 |
raise errors.HotplugError("Try hotplug only in running instances.") |
|
2043 |
v_major, v_min, _, _ = match.groups() |
|
2044 |
if (int(v_major), int(v_min)) < (1, 0): |
|
2045 |
raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0") |
|
2046 |
|
|
2038 | 2047 |
def _CallHotplugCommand(self, name, cmd): |
2039 | 2048 |
output = self._CallMonitorCommand(name, cmd) |
2040 | 2049 |
# TODO: parse output and check if succeeded |
b/lib/rpc_defs.py | ||
---|---|---|
300 | 300 |
("extra", None, "Extra info for device (dev_path for disk)"), |
301 | 301 |
("seq", None, "Device seq"), |
302 | 302 |
], None, None, "Hoplug a device to a running instance"), |
303 |
("hotplug_supported", SINGLE, None, constants.RPC_TMO_NORMAL, [ |
|
304 |
("instance", ED_INST_DICT, "Instance object"), |
|
305 |
], None, None, "Check if hotplug is supported"), |
|
303 | 306 |
] |
304 | 307 |
|
305 | 308 |
_IMPEXP_CALLS = [ |
b/lib/server/noded.py | ||
---|---|---|
631 | 631 |
return backend.HotplugDevice(instance, action, dev_type, device, extra, seq) |
632 | 632 |
|
633 | 633 |
@staticmethod |
634 |
def perspective_hotplug_supported(params): |
|
635 |
"""Checks if hotplug is supported. |
|
636 |
|
|
637 |
""" |
|
638 |
instance = objects.Instance.FromDict(params[0]) |
|
639 |
return backend.HotplugSupported(instance) |
|
640 |
|
|
641 |
@staticmethod |
|
634 | 642 |
def perspective_migration_info(params): |
635 | 643 |
"""Gather information about an instance to be migrated. |
636 | 644 |
|
b/test/py/cmdlib/instance_unittest.py | ||
---|---|---|
1975 | 1975 |
nics=[(constants.DDM_ADD, -1, {})], |
1976 | 1976 |
hotplug=True) |
1977 | 1977 |
self.ExecOpCode(op) |
1978 |
self.assertTrue(self.rpc.call_hotplug_supported.called) |
|
1978 | 1979 |
self.assertTrue(self.rpc.call_hotplug_device.called) |
1979 | 1980 |
|
1980 | 1981 |
def testAddNicWithIp(self): |
... | ... | |
2065 | 2066 |
nics=[(constants.DDM_MODIFY, 0, {})], |
2066 | 2067 |
hotplug=True) |
2067 | 2068 |
self.ExecOpCode(op) |
2069 |
self.assertTrue(self.rpc.call_hotplug_supported.called) |
|
2068 | 2070 |
self.assertTrue(self.rpc.call_hotplug_device.called) |
2069 | 2071 |
|
2070 | 2072 |
def testRemoveLastNic(self): |
... | ... | |
2089 | 2091 |
nics=[(constants.DDM_REMOVE, 0, {})], |
2090 | 2092 |
hotplug=True) |
2091 | 2093 |
self.ExecOpCode(op) |
2094 |
self.assertTrue(self.rpc.call_hotplug_supported.called) |
|
2092 | 2095 |
self.assertTrue(self.rpc.call_hotplug_device.called) |
2093 | 2096 |
|
2094 | 2097 |
def testSetOffline(self): |
... | ... | |
2177 | 2180 |
}]], |
2178 | 2181 |
hotplug=True) |
2179 | 2182 |
self.ExecOpCode(op) |
2183 |
self.assertTrue(self.rpc.call_hotplug_supported.called) |
|
2180 | 2184 |
self.assertTrue(self.rpc.call_blockdev_create.called) |
2181 | 2185 |
self.assertTrue(self.rpc.call_blockdev_assemble.called) |
2182 | 2186 |
self.assertTrue(self.rpc.call_hotplug_device.called) |
... | ... | |
2190 | 2194 |
{}]], |
2191 | 2195 |
hotplug=True) |
2192 | 2196 |
self.ExecOpCode(op) |
2197 |
self.assertTrue(self.rpc.call_hotplug_supported.called) |
|
2193 | 2198 |
self.assertTrue(self.rpc.call_hotplug_device.called) |
2194 | 2199 |
self.assertTrue(self.rpc.call_blockdev_shutdown.called) |
2195 | 2200 |
self.assertTrue(self.rpc.call_blockdev_remove.called) |
Also available in: Unified diff