我正在尝试为一些开源软件编写补丁,因为它不会完全我想要的东西 - 除了我根本不懂Python!我希望这很简单,但它正在打败我。
后台:我正在编写的补丁是用于管理KVM虚拟机群集的Ganeti,但它不支持KVM和Qemu的所有可能的命令行选项,例如USB传递,所以我试图修改它以允许这个。
kvm_cmd.extend()
用于添加将在VM启动时传递的KVM CLI args数组。如果参数是空格分隔的,则每个参数变为单独的字符串,例如-usb -device usb-host,hostbus=1,hostdev=14
变为"-usb", "-device", "usb-host,hostbus=1,hostdev=14"
。
我在编译代码后运行以下命令:
gnt-instance modify -H usb_pass="1;14"
我希望将其添加到现有的命令行参数列表"-usb -device usb-host,hostbus=1,hostdev=14"
中。这是我添加的代码(以及在其他地方声明变量; HV_USBPASSTHROUGH
是一个字符串,但这就是魔术发生的地方)
usb_pass = instance.hvparams[constants.HV_USBPASSTHROUGH]
if usb_pass:
usb_pass_arr = []
usb_pass_arr = usb_pass.split(";")
kvm_cmd.extend(["-usb", "-device", "usb-host,hostbus=%s,hostaddr=%s" %
usb_pass_arr])
使用上面的代码运行上面的命令时出现以下错误:Could not start instance: Error while executing backend function: not enough arguments for format string
答案 0 :(得分:7)
`%s
中有两个"usb-host,hostbus=%s,hostaddr=%s"
,但只提供一个参数,一个列表,其中包含一个元组。
使用
"usb-host,hostbus=%s,hostaddr=%s" % tuple(usb_pass_arr)
tuple() builtin将迭代转换为元组。
答案 1 :(得分:3)
更改
"usb-host,hostbus=%s,hostaddr=%s" % usb_pass_arr
到
"usb-host,hostbus=%s,hostaddr=%s" % tuple(usb_pass_arr)
此外,usb_pass_arr
不需要预先初始化,因为split()
会返回一个新列表。
答案 2 :(得分:3)
你已经得到了"old" style formatting的答案;将new style formatting与.format()
一起使用,您可以使用variable-length argument syntax执行以下操作,自动将usb_pass
解包为format()
的函数参数:
'usb-host,hostbus={},hostaddr={}'.format(*usb_pass)
答案 3 :(得分:1)
您需要做的就是将usb_pass_arr
作为元组传递,这是string formatting所期望的。
usb_pass = instance.hvparams[constants.HV_USBPASSTHROUGH]
if usb_pass:
usb_pass_arr = [] #you can remove this line
usb_pass_arr = tuple(usb_pass.split(";")) #a tuple is an immutable list
kvm_cmd.extend(["-usb", "-device", "usb-host,hostbus=%s,hostaddr=%s" %
usb_pass_arr])
答案 4 :(得分:1)
正如人们已经写过的那样,您需要使用tuple(usb_pass_arr)
将列表转换为元组。
请参阅python docs中的this段:
如果format需要单个参数,则值可以是单个非元组对象。否则,值必须是具有格式字符串指定的项目数的元组,或者是单个映射对象(例如,字典)。
答案 5 :(得分:0)
粗略猜测 - 您需要使用此代码:
"usb-host,hostbus=%s,hostaddr=%s" % (usb_pass_arr[0], usb_pass_arr[1])
答案 6 :(得分:0)
嗨大卫莫顿和其他任何感兴趣的人,这是Ganeti 2.6.0 USB传递每个实例的单个USB设备;
diff -r -c ganeti-2.6.0_original/lib/constants.py ganeti-2.6.0_changed/lib/constants.py
*** ganeti-2.6.0_original/lib/constants.py 2012-07-27 12:31:48.000000000 +0100
--- ganeti-2.6.0_changed/lib/constants.py 2012-10-04 13:46:15.881572099 +0100
***************
*** 770,775 ****
--- 770,776 ----
HV_KVM_USE_CHROOT = "use_chroot"
HV_CPU_MASK = "cpu_mask"
HV_MEM_PATH = "mem_path"
+ HV_USBPASSTHROUGH = "usb_pass"
HV_BLOCKDEV_PREFIX = "blockdev_prefix"
HV_REBOOT_BEHAVIOR = "reboot_behavior"
***************
*** 824,829 ****
--- 825,831 ----
HV_KVM_USE_CHROOT: VTYPE_BOOL,
HV_CPU_MASK: VTYPE_STRING,
HV_MEM_PATH: VTYPE_STRING,
+ HV_USBPASSTHROUGH: VTYPE_STRING,
HV_BLOCKDEV_PREFIX: VTYPE_STRING,
HV_REBOOT_BEHAVIOR: VTYPE_STRING,
}
***************
*** 1809,1814 ****
--- 1811,1817 ----
HV_MEM_PATH: "",
HV_REBOOT_BEHAVIOR: INSTANCE_REBOOT_ALLOWED,
HV_CPU_MASK: CPU_PINNING_ALL,
+ HV_USBPASSTHROUGH: "",
},
HT_FAKE: {
},
Only in ganeti-2.6.0_changed/lib/: .dir
Only in ganeti-2.6.0_changed/lib/: _generated_rpc.py
Only in ganeti-2.6.0_changed/lib/http: .dir
Only in ganeti-2.6.0_changed/lib/hypervisor: .dir
diff -r -c ganeti-2.6.0_original/lib/hypervisor/hv_kvm.py ganeti-2.6.0_changed/lib/hypervisor/hv_kvm.py
*** ganeti-2.6.0_original/lib/hypervisor/hv_kvm.py 2012-07-27 13:27:41.000000000 +0100
--- ganeti-2.6.0_changed/lib/hypervisor/hv_kvm.py 2012-10-04 13:46:54.993572107 +0100
***************
*** 490,495 ****
--- 490,496 ----
constants.HV_VHOST_NET: hv_base.NO_CHECK,
constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
+ constants.HV_USBPASSTHROUGH: hv_base.NO_CHECK,
constants.HV_REBOOT_BEHAVIOR:
hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
***************
*** 1257,1262 ****
--- 1258,1268 ----
kvm_nics = instance.nics
hvparams = hvp
+ usb_pass = instance.hvparams[constants.HV_USBPASSTHROUGH]
+ if usb_pass:
+ usb_pass_arr = usb_pass.split(";")
+ kvm_cmd.extend(["-usb", "-device", "usb-host,hostbus=%s,hostaddr=%s" % tuple(usb_pass_arr)])
+
return (kvm_cmd, kvm_nics, hvparams)
def _WriteKVMRuntime(self, instance_name, data):
Only in ganeti-2.6.0_changed/lib/impexpd: .dir
Only in ganeti-2.6.0_changed/lib/masterd: .dir
diff -r -c ganeti-2.6.0_original/lib/query.py ganeti-2.6.0_changed/lib/query.py
*** ganeti-2.6.0_original/lib/query.py 2012-07-27 12:31:48.000000000 +0100
--- ganeti-2.6.0_changed/lib/query.py 2012-10-04 13:46:26.625572103 +0100
***************
*** 1745,1750 ****
--- 1745,1751 ----
constants.HV_NIC_TYPE: "NIC_type",
constants.HV_PAE: "PAE",
constants.HV_VNC_BIND_ADDRESS: "VNC_bind_address",
+ constants.HV_USBPASSTHROUGH: "usb_pass",
}
fields = [
Only in ganeti-2.6.0_changed/lib/rapi: .dir
Only in ganeti-2.6.0_changed/lib/server: .dir
Only in ganeti-2.6.0_changed/lib/tools: .dir
Only in ganeti-2.6.0_changed/lib/utils: .dir
Only in ganeti-2.6.0_changed/lib/: _vcsversion.py
Only in ganeti-2.6.0_changed/lib/watcher: .dir